On 17.08.2007 16:20 John Siracusa wrote:

> On 8/15/07, Michael Lackhoff <[EMAIL PROTECTED]> wrote:
>>     my $db = My::DB->new();
>>
>>     $db->do_transaction(
>>         sub {
>>             my $o = My::Thing->new();
>>             $o->foo(123);
>>             $o->bar(456);
>>             $o->save;
>>             die "Does it rollback?";
>>         }
>>     );
>>
>> This code does _not_ do a rollback.
> 
> When running under Apache::DBI, this line issues a rollback:
> 
>     warn $o->db->dbh();

So, if I understand it right, there are really two problems:
- no rollback when it should be (my do_transaction above)
- a rollback when there should be none (your warn)

> Apache::DBI::reset_startup_state()
> And there you have it.  The $dbh that belongs to the $db that you
> called do_transaction() on has now been rolled back, and it's had its
> AutoCommit attribute set back to what it was on connect (1 in your
> case).

I must admit that I don't really understand what is going wrong in
reset_startup_state but even if I comment the call to
reset_startup_state out in Apache::DBI (as suggested before) the above
do_transaction code still doesn't roll back. So I cannot see how the
detailed sequence you show, leading to reset_startup_state, does explain
why my do_transaction doesn't roll back.

> So, the question is, what do we do to fix this?  Obviously, one work
> around is to pass the same $db around to all objects.  You can also
> change your init_db() routine in your common base class to be this
> instead:
> 
>     our $DB;
>     sub init_db { $DB ||= My::DB->new }

Until the experts find a better solution I have done something very
similar (only with a closure instead of the global variable).
At an early stage of every request I reset $DB (don't know if this is
really necessary) to be sure that transactions do not span requests.
A Cleanup handler now does a rollback on this $DB. Looks good so far.

> But really, I'd like to solve this somehow so the default way works as
> well.  It would be nice if I could ask Apache::DBI not to call
> reset_startup_state(), perhaps by passing a special connect attribute:
> 
>   DBI->connect(..., { private_Apache_DBI_No_Reset => 1, ... });

As I said, at least in my code it doesn't make any difference.

> Finally, I suppose I could change the default implementation of
> init_db() to be more like this instead:
> 
>     sub init_db { $DB ||= Rose::DB->new }
> 
> But that'd be quite a behavior change, and it'd have its own set of problems.

What are the problems here? Since I adopted this for the time being it
would be nice to know what I have to expect...

Thanks for digging into it
- Michael




-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
Rose-db-object mailing list
Rose-db-object@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rose-db-object

Reply via email to