Re: Cancelling idle in transaction state

From: Craig Ringer <craig(at)postnewspapers(dot)com(dot)au>
To: Simon Riggs <simon(at)2ndQuadrant(dot)com>
Cc: Kris Jurka <books(at)ejurka(dot)com>, Joachim Wieland <joe(at)mcknight(dot)de>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Hannu Krosing <hannu(at)2ndquadrant(dot)com>, James Pye <lists(at)jwp(dot)name>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Cancelling idle in transaction state
Date: 2009-12-30 12:30:23
Message-ID: 4B3B47DF.4000709@postnewspapers.com.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 30/12/2009 7:37 PM, Simon Riggs wrote:

> Can JDBC accept a NOTICE, yet throw an error? NOTICEs have a SQLState
> field just like ERRORs do, so you should be able to special case that.

The JDBC driver would have to throw when the app code next interacted
with the connection object anyway. It can't asynchronously throw an
exception. Since the next interaction that can throw SQLException() is
likely to be setup for or execution of a query, I'm not sure it makes
any difference to the JDBC user whether query cancellation is reported
as a NOTICE or an ERROR behind the scenes.

Since the proposed patch leaves cancelled transactions in the error
state, rather than closing them and leaving the connection clean and
idle, it doesn't matter much if a client doesn't understand or check for
the NOTICE. The app code will try to do work on the connection and that
work will fail because the transaction is aborted, resulting in a normal
SQLException reporting that the "current transaction is aborted ...".

JDBC-using code has to be prepared to handle exceptions at any point of
interaction with the JDBC driver anyway, and any code that isn't is
buggy. Consequently there's LOTS of buggy JDBC code out there :-( as
people often ignore exceptions thrown during operations they think
"can't fail". However, such buggy code is already broken by
pg_cancel_backend() and pg_terminate_backend(), and won't be broken any
more or differently by the proposed change, so I don't see a problem
with it.

Personally, I'd be happy to leave the JDBC driver as it was. It might be
kind of handy if I could getWarnings() on the connection object without
blocking so I could call it before I executed a statement on the
connection ... but that'd always introduce a race between transaction
cancellation/timeout and statement execution, so code must always be
prepared to handle timeout/cancellation related failure anyway.

As you say, the driver can special-case connection cancelled NOTICE
mesages as errors and throw them at next user interaction it wants. But
I'm not sure that's anything more than a kind of nice-to-have cosmetic
feature. If the JDBC driver handled the NOTICE and threw a more
informative SQLException to tell the app why the transaction was dead,
that'd be nice, but hardly vital. It'd want to preserve the notice as an
SQLWarning as well.

> I understand that this will mean that we are enhancing the protocol for
> this release, but I don't have a better suggestion.

Only in an extremely backward compatible way - and it's more of a
behavior change for the backend than a protocol change. Pg's backends
change behaviour a whole lot more than that in a typical release...

>> The only downside I can see is that a client would get confused if:
>>
>> 1) Transaction starts.
>> 2) Idle transaction is killed and error message is given.
>> 3) Client issues rollback
>> 4) Client gets error message from saying the transaction was cancelled.

For JDBC users, "there is no transaction in progress" is only reported
as a SQLWarning via getWarnings(), so I'd be surprised if anything used
it for more than logging or debugging purposes.

> Are you saying that the client should send rollback and that it should
> generate no message?

--
Craig Ringer

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tatsuo Ishii 2009-12-30 12:46:35 Re: exec_execute_message crash
Previous Message Kris Jurka 2009-12-30 12:28:01 Re: Cancelling idle in transaction state