1

I've run into an issue when stress testing mod_perl that the database connections are going away. I suspect that processes are sharing database connections, causing the issue.

But I've followed all instructions for Apache::DBI, and can't figure this out.

I'm making the connections in the child process and not in startup.pl. But when I examine the $dbh returned by each child from the DBI->connnect, the address is the same for every httpd process. Firstly, if this is working properly and reconnecting for each process, should the address returned by DBI->connect be different for each child process? I've assumed so, but as far as I can tell the core C code in DBI (dbih_setup_handle) is managing this and is returning the same address. So maybe I'm not understanding what it means to reconnect in the child.

Am I reconnecting properly if the $dbh handles are the same?

lschult2
  • 588
  • 2
  • 5
  • 16

1 Answers1

0

It sounds like you are establishing the database connection in a <perl>...</perl> section in your startup config, or in a module loaded at startup, and keeping it around until forked processes attempt to use it.

Unfortunately you can't get away with this. You'll need to somehow make sure that new processes get new connections.

My solution to this problem was a central function to obtain a dbh that kept track of what $$ (the current process id) was when the connection was established. If when handing over the connection, the function found that $$ had changed, it would dispose of any existing connections without closing them, and create a new one:

my $_dbh;
my $pid;

sub dbh {
        if($pid != $$) {
                $_dbh = DBI->connect(...);
                $pid = $$;
        }
        return $_dbh;
}

Any code that wanted to use the database would first call dbh() to obtain a database handle, and let it create a new one if necessary, or hand over a previously established connection if it can be used.

Michael Slade
  • 13,802
  • 2
  • 39
  • 44
  • Michael, I am not establishing any connections in startup.pl in an attempt to avoid this issue. All the connections are established by the child. But when I examine the addresses of the $dbh for each child, the addresses are the same. But since those are virtual addresses relative to the child, that may or may not mean the connection is being shared. This is what I am trying to figure out. How can I be sure the connection isn't being shared? – lschult2 May 20 '12 at 14:20
  • 3
    If the forked child server processes all behave identically up to the point where they open the database handle, then they will have identical addresses, but these are in separate process memory spaces so it's not an issue. – Michael Slade May 20 '12 at 14:54
  • So this then answers the question. I am doing it correctly even though the $dbh have the same address. ab stress tests confirm this by not failing. (I'm not sure how to select Michael's comment as the "answer") – lschult2 May 21 '12 at 14:27