Perrin Harkins <[EMAIL PROTECTED]> wrote:
> I've never seen Apache::DBI or connect_cached return a dead handle.  I 
> have had problems in the past with forking apps where I get back a 
> handle that still pings but has been shared across processes so it no 
> longer really works.  Were you doing something with forking?  Or maybe 
> opening handles during startup before apache forks?

        Perrin, Ask Bjoern, Tim,

                I am opening a handle before apache forks. However, I was
able to verify that Apache::DBI wasn't loaded yet at that point (no
$INC{'Apache/DBI.pm'}), and I was issuing a disconnect() before the fork
took place.

                So then I got rid of Apache::DBI entirely, deciding to rely
entirely on DBI->connect_cached to do it's own pinging and reconnecting. No
such luck. Inexplicably, I'd get a dead handle back, that said something
like "postgres server shutting down during query" (I don't have the exact
error message anymore, but it was something like that).

                ... so *then* I tried explicitly calling disconnect() on
these handles if ping() fails. disconnect() would fail because the handle
was "already disconnected", and the handle did *not* disappear out of
CachedKids.

                Thus my solution in a previous message, which Tim so fondly
called a "hack". :) It works in an extremely paranoid manner, wrapping both
the ping and disconnect methods inside an eval(), and explicitly deleting
the entry from CachedKids itself.

        Going forward:

                I think disconnect() should remove the handle from
{CachedKids} even if the handle is already disconnected. Common sense
dictates that you don't want an already disconnected handle to stick around
in your cache.

                Maybe Apache::DBI should push a PostConfigHandler into the
server that disconnects *every* DBI handle active before apache forks? Is
there a valid use case for having the same DBI handle replicated across a
bunch of apache child processes?

                When Apache::DBI refreshes it's database handle [~line 127],
it doesn't look like it's disconnecting the old one. What if the old handle
is in a connected, but unpingable state?

                Why is Apache::DBI maintaining it's own cache in the first
place? Shouldn't DBI->connect_cached be able to maintain that for us? Which
leads me to:

                Is there an easy way to enumerate *all* cached database
handles in DBI? The closest i've been able to come is to enumerate the
{CachedKids} of a specific driver handle, which I grab by using the
(undocumented) DBI->driver() method.

                As far as Tim's comment about "saving the world", I never
realised that would become a full time job of it's own. ;-) I'm willing to
refactor Apache::DBI when I have time (maybe even tonight). After browsing
through it's code, I must warn you that while I would keep the interface the
same, I would change it's behaviour a fair bit (mainly the points listed
above). If this is cool with everyone, I'll proceed... if not, there's I'll
stick with my hack, there's plenty of other code I could be writing/fixing.
:)

                        - Tyler

Reply via email to