Hi there,

Way back in December 2012 I posted a query to this list with the subject
"Possible database handle leak in DBI?".  There were a few replies to my
query, which can be found at
https://groups.google.com/forum/#!topic/perl.dbi.users/nElyR6hFka8
but no conclusive answer.

The lack of follow up was partly because we had our Christmas/summer break
and then in the new year there were other problems to deal with.  Also the
issue seemed to occur less frequently, so tracking it down got put on the
backburner, where it has remained until now...

Recently the problem has been occurring more frequently again, causing our
mysql server to run out of connections.  We've papered over the problem by
increasing the maximum number of connections and restarting our web server
each night.  But it would be much more satisfying to figure out what is
going on here!

Quite a few things have changed since my post of 15 months ago (newer versions
of DBI, DBD::mysql, mysql etc, plus our Apache now uses fcgid rather than
fastcgi).  I know I should give all the relevant version numbers, but given that
the problem has persisted over multiple versions I'm not sure that would help
all that much.

Instead I'll describe the one new fact that my recent debugging efforts have
turned up.  Hopefully this may allow someone with a deeper understanding
of the perl DBI and/or DBD::mysql packages to suggest what might be happening
here, or at least some more debugging strategies I could try...

First, a brief recap.  We have a web-based application that runs as a FosWiki 
plugin under Apache/fcgid.  The database connection used by this application 
should be persistent due to the application calling DBI->connect_cached() on
each invocation.

What we see is that most of the time this works correctly, but every so
often the call to connect_cached() doesn't find the cached connection and
so creates a new one.  This is despite a "mysql processlist" showing that
the old connection *is* still active.

The new piece of information that I have discovered recently is that on a
call to connect_cached() which *doesn't* return the cached database handle,
the database driver handle reference passed into connect_cached() has changed.
Since the dbh cache is obtained from "$drh->{CachedKids} ||= {}" I can now
understand why the cached handled is not found!

What I can't understand is why the driver handle passed into connect_cached()
has changed!  Especially since none of our application code knows or cares
about the existence of the driver handle (and as stated in the DBI pod, the
driver handle object is rarely seen or used in applications).

I've got 1000's of lines of debugging showing this happening.  Some of it
is my own, inserted as print statements or cluck calls directly into DBI.pm
and some of it the standard DBI debugging set to level 9.  There is way too
much to include in this message, but I've included some small extracts below
to illustrate what I am seeing.

>From these small extracts I don't expect anyone to be able to debug this
for me.  What I am hoping for though is perhaps some insight into the
circumstances in which the driver handle could change in this way.

One thing I did just notice is that our application calls connect_cached()
in the way shown in the DBI pod - that is:

      my $dbh = DBI->connect_cached(...)

I don't know enough about perl internals to know exactly what this does.
But I did wonder if something like the following might be better given the
persistent nature of our application provided by fcgid.

      my $dbi = new DBI;
      my $dbh = $dbi->connect_cached(...)

Any other advice would be greatly appreciated.

Thanks,

Duncan

Extract from Debugging:


    DBI::dr=HASH(0x7f7fe874fee8) trace level set to 0x0/9 (DBI @ 0x0/0) in DBI 
1.630-ithread (pid 18887)
    DBI 1.630-ithread default trace level set to 0x0/9 (pid 18887 pi 
7f7ff7703000) at DBI.pm line 1494 via UM.pm line 191
    ...
    No cached handle - creating new connection, dbh = 
DBI::db=HASH(0x7f7fe86f8468)
    ...

    DBI::dr=HASH(0x7f7fe874fee8) trace level set to 0x0/9 (DBI @ 0x0/0) in DBI 
1.630-ithread (pid 18887)
    DBI 1.630-ithread default trace level set to 0x0/9 (pid 18887 pi 
7f7ff7703000) at DBI.pm line 1494 via UM.pm line 450
    ...
    Using cached handle, dbh = DBI::db=HASH(0x7f7fe86f8468)
    ...

    <lots of repetitions of the above>

    ...

    DBI::dr=HASH(0x7f7fe299c5e8) trace level set to 0x0/9 (DBI @ 0x0/0) in DBI 
1.630-ithread (pid 18887)
    DBI 1.630-ithread default trace level set to 0x0/9 (pid 18887 pi 
7f7ff7703000) at DBI.pm line 1494 via UM.pm line 191
    ...
    No cached handle - creating new connection, dbh = 
DBI::db=HASH(0x7f7fe2819db0)
    ...


Reply via email to