[CDBI] prepared statements and InactiveDestroy

Perrin Harkins perrin at elem.com
Mon Nov 7 18:08:30 GMT 2005


On Mon, 2005-11-07 at 11:59 +0100, Aaron Ross wrote:
> Hi,
> 
> > I'm writing a Class::DBI app which fork()'s where both parent and  child 
> > need to keep the DBI handle.  Hence, I'm using  $dbh-> {InactiveDestroy} 
> 
> You can't keep a DB handle open across a fork. Reconnect in the child 
> using the same parameters.

Yes, but also set InactiveDestroy in the child, or the original handle
will no longer work in the parent.  (This took a lot of debugging to
figure out.)  It may differ by database, but this is definitely the case
with MySQL.

Here's a modification we made to Ima::DBI which makes it auto-reconnect
if you try to use it in a forked process:

sub _mk_db_closure {
	my ($class, $dsn, $user, $pass, $attr) = @_;
        $attr ||= {};
    
	my $dbh;
	my $process_id = $$;
	return sub {
		# set the PID in a private cache key to prevent us
		# from sharing one with the parent after fork.  This
		# is better than disconnecting the existing $dbh since
		# the parent may still need the connection open.  Note
		# that forking code also needs to set InactiveDestroy
		# on all open handles in the child or the connection
		# will be broken during DESTROY.
		$attr->{private_cache_key_pid} = $$;

                # reopen if this is a new process or if the connection
                # is bad
		if ($process_id != $$ or 
                    not ($dbh && $dbh->FETCH('Active') && $dbh->ping)) {
                    $dbh = DBI->connect_cached($dsn, $user, $pass, $attr);
                    $process_id = $$;
		}
		return $dbh;
	};

}

- Perrin





More information about the ClassDBI mailing list