You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Jay Buffington <ja...@gmail.com> on 2006/09/07 21:29:27 UTC
Re: Using Apache::DBI
Reviving a thread 4 months later...
On 5/10/06, Perrin Harkins <pe...@elem.com> wrote:
> On Wed, 2006-05-10 at 10:26 -0700, Jay Buffington wrote:
> > At first I was caching the database handle myself when running outside
> > of mod_perl. In mod_perl I was relying on Apache::DBI returning the
> > same handle every time I called connect(). That didn't work.
>
> What didn't work about it? If you use the same parameters, you should
> always get the same handle.
Ohhh, I misunderstood. It's not a pool of pools. "Practical mod_perl"
refers to a 'pool' of connections
(http://modperlbook.org/html/ch20_01.html#pmodperl-CHP-20-SECT-1). I
took this to mean that it maintains several connections for each
connection string, but after reading through the Apache::DBI source I
see that the pool he is referring to is the different connection
strings.
But, that handle might have expired, so it is possible to get a
different handle. I'm worried that it's not safe to do this:
use Apache::DBI;
use DBI;
my $dbh = DBI->connect(...);
$dbh->do("insert values('foo') into bar');
# time passes... and then:
my $new_dbh = DBI->connect(...);
$new_dbh->commit();
Since transactions are handle specific and there is no guarantee that
I'm going to get the exact same handle, I'm scared my insert might not
get committed.
Of course, I might just be whining about a corner case that never
exists in real life. If the handle is active when I do the insert,
it's probably going to be active when I do the commit moments later.
> > I considered allocating a handle in the pnotes() at the beginning of
> > every request using a PerlInitHandler, but that is expensive,
> > especially since many requests don't even use a handle.
>
> Are the requests that don't need a database running mod_perl code? If
> not, they should be served by a proxy.
Good point. Static requests are served from a squid cache a light
weight web server (Perlbal).
Thanks,
Jay
Re: Using Apache::DBI
Posted by Jonathan Vanasco <mo...@2xlp.com>.
On Sep 7, 2006, at 4:40 PM, Jay Buffington wrote:
> This solves a problem I was having some time ago while implementing
> ecommerce (verisign):
>
> 1. insert customer's info
> 2. authorize credit card
> 3. log authorization response to database
> 4. if auth fails roll back #1, but keep #3
Nested transactions for problems like that require DB supported
nested transactions-- oracle and postgres have them ( i think ).
DBIx is just transaction aware- it lets you nest your transactions by
hijacking begin/commit|rollback. Errors on an inner transaction
create errors for the whole nested structure.
IE: You can't rollback to 1 from 3- you need to do that in the database.
It's useful for situations where you're wrapping a bunch of modules
or 'pages' into a larger chain of commands.
I usually avoid your problem by using different db handles per-child
-- one of which does not support transactions , is dedicated for all
logging issues, and only has write on a few tables.
Re: Using Apache::DBI
Posted by Jay Buffington <ja...@gmail.com>.
This solves a problem I was having some time ago while implementing
ecommerce (verisign):
1. insert customer's info
2. authorize credit card
3. log authorization response to database
4. if auth fails roll back #1, but keep #3
I was planning on solving this problem using Oracle's
AUTONOMOUS_TRANSACTION Pragma. I'll look into nested transactions and
see how these two differ.
Thanks,
Jay
On 9/7/06, Jonathan Vanasco <mo...@2xlp.com> wrote:
>
> take a look at:
>
> http://search.cpan.org/~crakrjack/DBIx-Transaction-0.008/
>
> which allows for nested transactions in a DBI handle.
Re: Using Apache::DBI
Posted by Jonathan Vanasco <mo...@2xlp.com>.
take a look at:
http://search.cpan.org/~crakrjack/DBIx-Transaction-0.008/
which allows for nested transactions in a DBI handle.
I use something homegrown and similar (but not stable enough for
cpan), that intercepts calls to connect/disconnect and treats them as
begin/end commands on a nested transaction
note that either solution aren't true db style nested transactions
( i think only pg and oracle have them anyways ). they just
intercept begin/end if you're already in a transaction.
Re: Using Apache::DBI
Posted by Perrin Harkins <pe...@elem.com>.
On Thu, 2006-09-07 at 12:29 -0700, Jay Buffington wrote:
> But, that handle might have expired, so it is possible to get a
> different handle.
It's not likely, but it is possible. You'd need to have some transient
error that caused the connection to die between DBI calls. (Not during
a call, since you have RaiseError on, right?)
> I'm worried that it's not safe to do this:
>
> use Apache::DBI;
> use DBI;
>
> my $dbh = DBI->connect(...);
> $dbh->do("insert values('foo') into bar');
>
> # time passes... and then:
>
> my $new_dbh = DBI->connect(...);
> $new_dbh->commit();
My approach is to keep AutoCommit on, and turn it off for the brief
periods where I want a transaction to span multiple statements.
{
local $dbh->{AutoCommit} = 0;
### do some SQL actions here
} # commit happens automatically here
> Of course, I might just be whining about a corner case that never
> exists in real life. If the handle is active when I do the insert,
> it's probably going to be active when I do the commit moments later.
If it worries you, you could modify Apache::DBI to die rather than
reconnect if the handle has been requested previously in the current
request. This is pretty easy to keep track of with pnotes.
- Perrin