Thread: taking actions on rollback (PHP)

taking actions on rollback (PHP)

From
Ivan Sergio Borgonovo
Date:
I've a set of statements...

pg_query('begin;');

pg_query('do stuff');
pg_query('do other stuff');

if(!pg_query('commit;')) {
    pg_query('rollback;');
    // DO SOME CLEANUP HERE
}

if something goes wrong the statement actually get rolled back... but
the pg_query('commit;') statement always succede so the cleanup never
get executed.
How am I going to see if the transaction succeeded without checking
what happens for each statement and getting the cleanup code execute?

thanks

--
Ivan Sergio Borgonovo
http://www.webthatworks.it


Re: taking actions on rollback (PHP)

From
Martijn van Oosterhout
Date:
On Sat, Apr 26, 2008 at 10:52:12PM +0200, Ivan Sergio Borgonovo wrote:
> How am I going to see if the transaction succeeded without checking
> what happens for each statement and getting the cleanup code execute?

You basically actually check for the errors in the earlier pg_query()
calls, since they will tell you. If you can't be bothered, you could
just do at the end of the transaction:

if( !pg_query("select 1") )
  pg_query("rollback');
  // DO CLEANUP HERE
}
else
{ pg_query("commit"); }

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Please line up in a tree and maintain the heap invariant while
> boarding. Thank you for flying nlogn airlines.

Attachment

Re: taking actions on rollback (PHP)

From
Ivan Sergio Borgonovo
Date:
On Sat, 26 Apr 2008 23:14:07 +0200
Martijn van Oosterhout <kleptog@svana.org> wrote:

> On Sat, Apr 26, 2008 at 10:52:12PM +0200, Ivan Sergio Borgonovo
> wrote:
> > How am I going to see if the transaction succeeded without
> > checking what happens for each statement and getting the cleanup
> > code execute?
>
> You basically actually check for the errors in the earlier
> pg_query() calls, since they will tell you. If you can't be
> bothered, you could just do at the end of the transaction:

> if( !pg_query("select 1") )
>   pg_query("rollback');
>   // DO CLEANUP HERE
> }
> else
> { pg_query("commit"); }

I can guess the logic... but I'd like to be sure I got it.

Why does
if( !pg_query("commit;") )
doesn't report any error back?

So an error stays around and after a failure of any statement after
the begin all the following statement (on the same connection???) will
fail. Is it?

BTW your code had to be changed to
if( !@pg_query("select 1") )
  pg_query("rollback');
  // DO CLEANUP HERE
}
else
{ pg_query("commit"); }

Otherwise php get nervous, fail and the cleanup code doesn't get
executed and furthermore it seems that with a pending failed
transaction other statement fail too.
That was curious since I opened 2 pages from the same browser just to
check if the cleanup code was going to be executed and keep the form
I was submitting easy to be refilled with a back.

Form -> several errors +
ERROR:  current transaction is aborted, commands ignored until end of
transaction block

Testing page that give me a view on the tables that should be
cleaned up -> refresh ->
ERROR:  current transaction is aborted, commands ignored until end of
transaction block

With the added @ everything seemed to be OK.
I had to refresh a second time to get rid of the error.
I'd like to be sure I've understood how it works since I wouldn't
like the error went away just by chance and under heavy load I may
have troubles.

I'm using pg_connect not pg_pconnect.

Why did I get the
ERROR:  current transaction is aborted, commands ignored until end of
transaction block
from 2 different pages?

> Have a nice day,

thanks, you've been very helpful.

--
Ivan Sergio Borgonovo
http://www.webthatworks.it


Re: taking actions on rollback (PHP)

From
"Scott Marlowe"
Date:
On Sat, Apr 26, 2008 at 4:19 PM, Ivan Sergio Borgonovo
<mail@webthatworks.it> wrote:
>
>  With the added @ everything seemed to be OK.

No, the @ is just making php quietly swallow the postgresql errors
that are being returned.  It changes nothing in operation.

>  I had to refresh a second time to get rid of the error.
>  I'd like to be sure I've understood how it works since I wouldn't
>  like the error went away just by chance and under heavy load I may
>  have troubles.

I'm pretty sure you're not undestanding how it works.

With postgresql, ANY error in a transaction results in the whole
transaction being rolled back.  Any commands thrown at the database
after that result in this error message:

>  Why did I get the
>  ERROR:  current transaction is aborted, commands ignored until end of
>  transaction block
>  from 2 different pages?

because each page got an error in a statement inside its transaction.
It then issued the above error over and over as you attempted to
execute the next statement.

In postgresql, without using savepoints, any error in the transaction
will cause the whole transaction to fail, whether you type commit or
rollback at the end.  All the changes are lost either way.

So, there's no "cleanup" to do for the transaction, it's already cleaned up.

Re: taking actions on rollback (PHP)

From
Ivan Sergio Borgonovo
Date:
On Sat, 26 Apr 2008 20:58:06 -0600
"Scott Marlowe" <scott.marlowe@gmail.com> wrote:

> On Sat, Apr 26, 2008 at 4:19 PM, Ivan Sergio Borgonovo
> <mail@webthatworks.it> wrote:
> >
> >  With the added @ everything seemed to be OK.
>
> No, the @ is just making php quietly swallow the postgresql errors
> that are being returned.  It changes nothing in operation.

That seems to be necessary otherwise the transaction won't be
"closed" and no other statement would be accepted.

> >  I had to refresh a second time to get rid of the error.
> >  I'd like to be sure I've understood how it works since I wouldn't
> >  like the error went away just by chance and under heavy load I
> > may have troubles.

> I'm pretty sure you're not undestanding how it works.

> With postgresql, ANY error in a transaction results in the whole
> transaction being rolled back.  Any commands thrown at the database
> after that result in this error message:

That's exactly why I started to use transactions.

> >  Why did I get the
> >  ERROR:  current transaction is aborted, commands ignored until
> > end of transaction block
> >  from 2 different pages?

> because each page got an error in a statement inside its
> transaction. It then issued the above error over and over as you
> attempted to execute the next statement.

That would make postgresql a BIG BIG BIG lock.
If every rollback is going to block all connections that's a problem.
That's exactly why I pointed out that I was using plain pg_connect
and not pg_pconnect (pooled connection).
So I'd expect that if one page, that's using one connection, got
stuck ignoring other statement cos it has a failed transaction
pending... another page using another connection can still at least
read the DB.
The @ seems to be necessary otherwise php will stop execution and
leave the transaction open and php will never reach the cleanup code.

I think the code would work even this way:
if( !pg_query("select 1") )
// commit even if failed just to signal end of transaction
  pg_query("commit');
  // DO CLEANUP HERE
}
else
{ pg_query("commit"); }


Still... why did I get
ERROR:  current transaction is aborted, commands ignored until end of
transaction block
from *another page* even if I was not using pg_pconnect?
What is the state of the DB after the first failed statement?

Furthermore... what's going to happen if I use pg_pconnect?
Managing transactions is going to become much harder.
Is there a chance something like this is going to happen?

pg_query("begin;");
pg_query("statement from page 1");
pg_query("statement from page 1");
// FAIL, php code reach the end and connection is freed
pg_query("statement from page 1");
pg_query("statement from page 2 kick in in same connection");
// even statement from page 2 fail cos a transaction is pending on
the same connection

> In postgresql, without using savepoints, any error in the
> transaction will cause the whole transaction to fail, whether you
> type commit or rollback at the end.  All the changes are lost
> either way.

> So, there's no "cleanup" to do for the transaction, it's already
> cleaned up.

That would be great if the framework I'm working with would be
transactional. So there are things done before my transaction that
still need cleanup.

--
Ivan Sergio Borgonovo
http://www.webthatworks.it


Re: taking actions on rollback (PHP)

From
Martijn van Oosterhout
Date:
On Sun, Apr 27, 2008 at 11:09:36AM +0200, Ivan Sergio Borgonovo wrote:
> > because each page got an error in a statement inside its
> > transaction. It then issued the above error over and over as you
> > attempted to execute the next statement.
>
> That would make postgresql a BIG BIG BIG lock.
> If every rollback is going to block all connections that's a problem.
> That's exactly why I pointed out that I was using plain pg_connect
> and not pg_pconnect (pooled connection).

Eh? Each page got an error in its own transaction. An error in one
transaction naturally does not affect any other concurrent
transactions.

> I think the code would work even this way:
> if( !pg_query("select 1") )
> // commit even if failed just to signal end of transaction
>   pg_query("commit');
>   // DO CLEANUP HERE
> }

True, for an aborted transaction COMMIT and ROLLBACK do the same thing.

> Still... why did I get
> ERROR:  current transaction is aborted, commands ignored until end of
> transaction block
> from *another page* even if I was not using pg_pconnect?
> What is the state of the DB after the first failed statement?

That other page also got an error. Given then you never check the
return result of any of the queries I suggest you look at the server
logs: any statements that caused an error should be logged.

> Furthermore... what's going to happen if I use pg_pconnect?
> Managing transactions is going to become much harder.
> Is there a chance something like this is going to happen?

There's a reason why pg_pconnect is not recommended. The usual method
is some kind of connection pooling that understands transactions.

> > So, there's no "cleanup" to do for the transaction, it's already
> > cleaned up.
>
> That would be great if the framework I'm working with would be
> transactional. So there are things done before my transaction that
> still need cleanup.

It's unclear to me what kind of cleanup you're talking about, so I
can't help you here.

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Please line up in a tree and maintain the heap invariant while
> boarding. Thank you for flying nlogn airlines.

Attachment

Re: taking actions on rollback (PHP)

From
Ivan Sergio Borgonovo
Date:
On Sun, 27 Apr 2008 11:26:33 +0200
Martijn van Oosterhout <kleptog@svana.org> wrote:

> > That would make postgresql a BIG BIG BIG lock.
> > If every rollback is going to block all connections that's a
> > problem. That's exactly why I pointed out that I was using plain
> > pg_connect and not pg_pconnect (pooled connection).

> Eh? Each page got an error in its own transaction. An error in one
> transaction naturally does not affect any other concurrent
> transactions.

"Eh?" was my same reaction. I'm going to check the logs... and be
sure I wasn't dreaming.
Do you confirm that if I wasn't dreaming and another page that should
have opened another connection with pg_connect did cause another

ERROR:  current transaction is aborted, commands ignored until end of
transaction block

there is something wrong with the Universe or at least with what's
happening with php/postgresql?

> > Furthermore... what's going to happen if I use pg_pconnect?
> > Managing transactions is going to become much harder.
> > Is there a chance something like this is going to happen?

> There's a reason why pg_pconnect is not recommended. The usual
> method is some kind of connection pooling that understands
> transactions.

Are there any guidelines about usng pg_pconnect?
Are you aware of some place that could enlighten me about the
troubles I may face and what I should take care of?

Explicitly using the resource param in pg_query doesn't look helpful.
PGSQL_CONNECT_FORCE_NEW actually fail the scope of using pg_pconnect.
For the transaction problem there is a proposed solution on the php
online manual... send a commit when the script closes in
register_shutdown_function(), so you avoid bookkeeping and you're
sure the transaction will be closed.
I still can't get the magic behing pg_pconnect.
When does a connection is considered freed?

This is interesting:
http://archives.postgresql.org/pgsql-general/2007-08/msg00660.php

And well since it doesn't seem I really need pg_pconnect and that
when I'll need connection pooling I'll go for pgpool... consider the
questions above just for the shake of understanding how things works
behind the scene.

> > > So, there's no "cleanup" to do for the transaction, it's already
> > > cleaned up.
> >
> > That would be great if the framework I'm working with would be
> > transactional. So there are things done before my transaction that
> > still need cleanup.

> It's unclear to me what kind of cleanup you're talking about, so I
> can't help you here.

Just to waste some bandwidth since this is absolutely not pg
related... I'm using an object provided by a framework that doesn't
use transactions. I'm enriching that object with other proprieties.
Part of the object is created by the framework and saved to DB. Then
control is passed to me and I add the other proprieties.
If for any reason my code fail... I've to cleanup the simpler object
created by the framework "by hand".

Using transactions on my part won't solve the problem that the
framework is not transactional... and I may still end up in mangled
objects... but still better than nothing.

thanks

--
Ivan Sergio Borgonovo
http://www.webthatworks.it


Re: taking actions on rollback (PHP)

From
Martijn van Oosterhout
Date:
On Sun, Apr 27, 2008 at 02:05:16PM +0200, Ivan Sergio Borgonovo wrote:
> "Eh?" was my same reaction. I'm going to check the logs... and be
> sure I wasn't dreaming.
> Do you confirm that if I wasn't dreaming and another page that should
> have opened another connection with pg_connect did cause another
>
> ERROR:  current transaction is aborted, commands ignored until end of
> transaction block
>
> there is something wrong with the Universe or at least with what's
> happening with php/postgresql?

Yes, if you're getting that message on a connection without having an
error on that connection then something is really wrong. Note, I've
never used PG with PHP so I can't help you with anything specific.

> This is interesting:
> http://archives.postgresql.org/pgsql-general/2007-08/msg00660.php

Yes, that's a pretty good summary of the problems with pconnect.

> If for any reason my code fail... I've to cleanup the simpler object
> created by the framework "by hand".

Ok...
Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Please line up in a tree and maintain the heap invariant while
> boarding. Thank you for flying nlogn airlines.

Attachment

Re: taking actions on rollback (PHP)

From
Hannes Dorbath
Date:
Martijn van Oosterhout wrote:
> Yes, if you're getting that message on a connection without having an
> error on that connection then something is really wrong. Note, I've
> never used PG with PHP so I can't help you with anything specific.

Turn on pgsql.auto_reset_persistent.

--
Best regards,
Hannes Dorbath