On Mon, Nov 29, 1999 at 01:19:53PM -0800, Randal L. Schwartz wrote:
> 
> [watch the followups... this is going to both the modperl
> and the DBI list...]
> 
> >>>>> "Ed" == Ed Park <[EMAIL PROTECTED]> writes:
> 
> Ed> each creates a network connection to DBI::ProxyServer, which
> Ed> creates a few persistent connections to the db server using the
> Ed> connect_cached method.
> 
> I hadn't noticed that until now.  Except I also noticed this...
> 
>            Note that the behaviour of this method differs in
>            several respects from the behaviour of the presistent
>            connections implemented by Apache::DBI.
> 
> Which scares me, but then doesn't go on to explain *what* those
> "several respects" are.  While I didn't pay anything for the
> documentation *or* DBI, so I should be grateful, this is the kind of
> sentence that any editor looking over *my* stuff would flag with a big
> "?". :) Never leave the reader with a sense of puzzlement -- either
> don't say anything, finish the thought, or tell them where to read
> more.
> 
> So, Tim, what *are* the differences, and when should we should we
> choose Apache::DBI vs DBI->connect_cached, and why?

The docs don't go into detail because, as they say:

        The exact behaviour of this method I<is liable to change>.
        If you intend to use it in any production applications your
        should discuss your needs in the dbi-users mailing list.

connect_cached is targeted, in part, for use with DBI::ProxyServer
to implement connection pooling. But, and it's a big but, the
current implementation of DBI::ProxyServer, as far as I know,
doesn't work in a way that would allow connect_cached to be useful.

Ignoring 'thread' (unsafe for production use) and 'debug' modes, the
normal 'fork' mode means that each client gets a seperate ProxyServer
process. And because of that, clients have no way to share connections
with each other.

I'd like to see a mode added to DBI::ProxyServer whereby a single
server process serviced multiple clients in a round-robin manner.
Obviously in this mode there's a risk of slow queries cloging up
(blocking) the proxy, but for many applications it would still be
very useful. Most significantly it would enable connect_cached to
be used to implement a (kind-of) connection pool.

Sadly I don't have the time to work on that. I'm not sure if Jochen
Wiedmann (the author of DBI::ProxyServer, DBD::Proxy and the RPC::*
modules they sit on) either has the time or is interested in doing the
work. On the other hand, given how useful this functionality would be,
I'm sure there must be someone out there willing to have a go at
implementing it. It can't be that hard. [Volunteers welcome but please
coordinate with Jochen and myself.]

Coming back to your original question, connect_cached is currently
a very simple cache:

    sub connect_cached {
        my $drh = shift;
        my ($dsn, $user, $auth, $attr)= @_;
        my $cache = $drh->FETCH('CachedKids');
        $drh->STORE('CachedKids', $cache = {}) unless $cache;
        my $key = join "~", $dsn, $user||'', $auth||'', $attr ? %$attr : ();
        my $dbh = $cache->{$key};
        return $dbh if $dbh && $dbh->FETCH('Active') && $dbh->ping;
        $dbh = $drh->connect(@_);
        $cache->{$key} = $dbh;  # replace, even if it failed
        return $dbh;
    }

Apache::DBI's connect method is slightly more involved. It has some
Apache specifics and also reblessing the handle into a different class
in order to disable the disconnect method.

One final point, I think that connect_cached would need to be modified
slightly before it would be used as a true 'connection pool'. Right now
it'll happily give you the same live database handle that some other
part of the system may still be using. That may be, er, bad. You can
get around that by adding dummy attributes to force whatever level of
uniqueness is desired, but that's the kind of open issue that meant
connect_cached was left with a warning sign and a plea for input.

I hope that helps.

Tim.

Reply via email to