Re: [INTERFACES] DBI driver and transactions - Mailing list pgsql-general

From Nigel J. Andrews
Subject Re: [INTERFACES] DBI driver and transactions
Date
Msg-id Pine.LNX.4.21.0302042203320.20150-100000@ponder.fairway2k.co.uk
Whole thread Raw
Responses Re: [INTERFACES] DBI driver and transactions
List pgsql-general
On Tue, 4 Feb 2003, Rudy Lippan wrote:

> On Mon, 3 Feb 2003, Nigel J. Andrews wrote:
>
> > Oh I give up. Trying to clarify what happens when I'm now seeing rollbacks
> > issued in AutoCommit => mode where I'm not doing any and it's certainly not me
> > since I've got a trap on my interface layer to DBI for that and it's not been
> > tripped at all.
> >
> IIRC, It will do a rollback for you on disconnect.

Yep, it was a disconnect that was doing that. What I wasn't expecting was a
disconnect on a cached connection (with others still open) to be rolling
back.

It sort of makes sense to do that on the assumption that each connection is
opened for a particular transaction and others are idle. However, there is only
one connection to the backend and to make that assumption the driver should
also not send any requests for a particular cached connection to the backend
until it sees a commit/rollback. Why? Well because it's silly to make the
assumption that a single cached connection close is terminating a transaction
when there can be another one interleaving queries with it. For example take
the situation:

Object or Library 1:
  dbh1 = DBI->connect_cached

Object or Library 2:
  dbh2 = DBI->connect_cached


main:

 do_selects_in_lib1();
 do_inserts_in_lib2();
 close_lib1_without_commit();
 ...all of a sudden here we find lib2's inserts have been rolled back.

It may be that I've taken an odd design route and that a more usual one is to
create a connection and pass that around instead of letting subsystems create
their own (it's not as though I don't need to pass the information to make the
connection around).

My point, however, is that the connect_cached method is multiplexing request
channels to a single processing unit. It is not normal for one such channel to
invalidate all others, or indeed validate (commit), all others. On the one hand
DBI is saying each channel is a separate entity, otherwise it wouldn't rollback
when only one closes, but on the other hand all channels are one, otherwise it
wouldn't allow query interleaving, i.e. would have locking on the channel to
the server.


> > So,
> >
> > a) anyone know of any problems,
> >
> > b) can I assume it is me and not just give up on this DBI stuff in the future (
> > I haven't got the time to rewrite my application now; not that I can't see it
> > being a particularly onerous task for what I use from DBI )
> >
> > c) can I just issue BEGIN, COMMIT, ROLLBACK when I want to via normal
> > $dbh->do(...) without causing myself even more problems?
> >
>
> Yes and no. DBD::Pg will stop you from calling those commands;
> however, I think that you can trick DBD::Pg by make it not look like a
> transaction command (eg. $dbh->do(q{/* Trick Pg */ BEGIN}) ); although, I
> have not tried it, and it is not recommended.
>
> I, for the most part, do:
>
> sub stuff {
>     local($dbi->{AutoCommit}) = 0;
>
>     eval {
>         #do transaction stuff.
>         $dbi->commit();
>     }; if (my $e = $@)
>         $dbi->rollback();
>     }
>    # $on exit $dbi->{AutoCommit} will go to 1 and DBD::Pg will call
>    # commit() for you
> }
>
> DBI now supports a begin_work method, but DBD::Pg does not have
> support for it at this time.

Interesting. Just wondering though, why the comment on exit calling
commit? Within your eval block you've already done the commit and dbi won't
issue another one until another statement is executed.


--
Nigel J. Andrews


pgsql-general by date:

Previous
From: Stephan Szabo
Date:
Subject: Re: not exactly a bug report, but surprising behaviour
Next
From: John Smith
Date:
Subject: Re: UPDATE slow