perl-modperl mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Tyler MacDonald <>
Subject Re: mod_perl2 DBI handle freshining problem solved "once and for all"...
Date Wed, 01 Feb 2006 22:06:22 GMT
Perrin Harkins <> wrote:
> > 	Yes and no. If you can't ping the server, but the TCP socket is
> > still open, that means you essentially have this TCP connection to the
> > server that's not being used, in an open state, for the rest of the lifetime
> > of your apache server instance. This could be a Bad Thing, say, if it's in
> > mid-transaction, keeping a table lock open...
> Sorry, but this sounds like total conjecture to me.

	I completely agree. :)

> You have to expect certain basic things to work, and one of them is that a
> connection which can't be ping'ed is not holding a table lock.

	I completely disagree. Here's some more conjecture: What if you
can't ping the connection because of a temporary TCP/IP problem (eg;
somebody tripping over the network cable)... the driver's ping timeout could
easily expire before the TCP/IP stack's timeout expires, the cable coule be
plugged back in, and then TCP/IP's happy, DBI experienced a ping timeout,
but the connection is not technically "closed". If this can happen on my SSH
sessions when my daughter yanks on my network cable, it could certainly
happen on a database driver.

	And here's some more conjecture: What if the ping just times out
because the server is really, really busy?

> If it is, this is a much lower-level bug than DBI should try to deal with.

	If DBI doesn't plan on using a cached database handle anymore, it
should at least disconnect() it and remove it's dangling reference from
CachedKids. I don't know if it does an explicit disconnect() itself in this
case, but I do know the handle reference (which is essentally garbage at
this point) is left laying around.
> I issue a rollback on all active connections at the end of every request. 
> Everyone who uses transactions at all should do that.

	I wrote DBIx::Transaction specifically so I wouldn't have to worry
about that anymore. ;-) It's so much easier just to

	$dbh->transaction(sub {
	  return $do_i_want_to_commit ? 1 : 0;

	especially now that I can nest them arbitrarily deep.

> > 	When I just let a database handle fall off the face of the earth I
> > generally get a warning like "DESTROY: issuing ROLLBACK for handle
> > destroyed without disconnect". So it seems like a part of that logic is
> > already in the new DBI.
> Apache::DBI overrides disconnect() to be a no-op, and connect_cached()
> doesn't.  (But Apache::DBI doesn't do this during startup.)

	Yeah, I ditched Apache::DBI early in diagnosing this problem. Then I
wrote that hack to solve it, which is what has started this whole thread. I
was happy just posting the hack and leaving it at that, but you guys keep
egging me on ;-)

> > 	I do know that after refactoring my code to not use Apache::DBI at
> > all, and not depend on connect_cached() to behave properly, (adding the
> > PostConfig and PreConnection handlers to be very paranoid about what happens
> > to the handles), the problem has gone away.
> That's too many changes at once to draw any conclusions.

	They were done one at a time. To the best of my memory:

	- Not using Apache::DBI came first. That made it so that after about
a dozen refreshes my database handles were OK again.

	- PreConnection handler came next, along with wrapping my
disconnect() call in an eval{}. That brought it down to 2 or 3 refreshes.

	- The PostConfig handler came next, along with deleting the dangling
references from CachedKids. I'm not sure if the CachedKids things helped,
but it certainly doesn't do any harm so I left it in. So these last two
changes may need to be diagnosed further.

> It currently checks to see if you've loaded Apache::DBI and sends all
> connect()/connect_cached() calls there, so that would have to be taken
> out to avoid a perpetual feedback loop.

	Aaaah. :)

		- Tyler

View raw message