Beatnik has asked for the wisdom of the Perl Monks concerning the following question:

I currently have several modules fetching data from a DB (with DBI). They all individually connect to the DB, fetch their data and close up ASAP. Authorisation data is passed along the constructor by the main code. I'm considering moving all opening/closing of the DB to the main code, and pass along a DB handle thru the constructor. The modules would only do plain fetching.

Altho having each module connect individually would be loads cleaner, it also would be slower and loads more DB stressing. Passing along the handle to the modules would probably be faster, but the modules will be loads more dependant on the main code (somehow killing the abstraction factor). The DB connections would be 'locked' longer, therefor restricting the number of simultaneous connections.

What are your thoughts on this?

Greetz
Beatnik
... Quidquid perl dictum sit, altum viditur.

Replies are listed 'Best First'.
Re (tilly) 1: Using DBI handle in several packages
by tilly (Archbishop) on Jun 03, 2001 at 04:43 UTC
    If you know how many clients could connect, just set the number of possible connections that high.

    Personally what I would do is have a single module that connects to the database, caches the handle, and returns it. Every other module just asks the single module to give them the appropriate connection, and gets it without worrying about whether a connect just happened or not. Then each module just has to never close it, and not leave any state.

    State you ask? Well yes. For instance if you create #tables in Sybase (ie connection-specific temporary tables) you should also delete them when you are done. To be sure that that kind of state is properly cleaned up what you can do is have the functions that create state use ReleaseAction to make sure that the state will be cleaned up appropriately.

    Of course that assumes that the authors of the modules can hold to a reasonable standard. To quote Larry Wall, Give people enough rope to hang themselves, and they'll usually figure out how not to, after several successes. It is your decision whether the people writing those modules have had enough successes already...

Re: Using DBI handle in several packages
by Vynce (Friar) on Jun 03, 2001 at 01:41 UTC

    I think you're wrong about your cleanliness assesment.

    I think it will be cleaner to pass them a DB handle, because then they don't care what DB they're operating on, and if the main code changes it so that 2 of them use one DB and 3 use another, you only have to change the main program. in short, think of the modules as "doing stuff to a database" rather than "doing stuff to database X", and think of main as "calling the modules on database X" -- because a different main could then use those same modules on a different database.

    .

    update: yes, but are they also passed what type of DB it is? it is perhaps better to pass them handles, so that one can use a BerkeleyDB and another use DBD::CSV ... and yes, you can pass that information, too, but a handle sums it all up, doesn't it?

    that's my take, anyway.

    .
      That data is passed to the modules by the main code anyway. The modules connect, fetch data and close up. :)

      Update: All data required for a clean connect is either passed along in constructor (User, Password, DB Type, DB Name, Port) or are Module vars (table name).

      Greetz
      Beatnik
      ... Quidquid perl dictum sit, altum viditur.
Re: Using DBI handle in several packages
by runrig (Abbot) on Jun 03, 2001 at 01:47 UTC
    Depends on how much opening and closing of the database there would be on the present typical execution and how long your application is open versus how long you actually need the database open (I usually find that database operations are the slowest part of an application, so you may as well keep a connection open). But one possibility is to have one module actually open and close the database, and and have the rest of the modules use that module's db handle.

    Have every module do a 'my $dbh = MyDBI->connect(...)' and in your MyDBI module, the first call actually connects while subsequent calls just reuse the same handle (stored perhaps in a package global variable).

    The disconnect would have to be at the end of the application I suppose.

    Update: I take it all (well, most of it) back. Use connect_cached() and just let every module connect, just don't disconnect until the end of the app.

    Another update:Looking at the docs for connect_cached(), I'm not sure the author really recommends it, so maybe my first suggestion is the way to go for production code.

      Altho connect_cached() looks nice, I'm still not sure I should be using it.
      Programming the Perl DBI lists it as (NEW) and also states 'it can also cause problems and should be used with care. The exact behaviour of this method is liable to change'.

      To answer your question (which you then took back), the number of requests made depends on the usage of the application.

      Greetz
      Beatnik
      ... Quidquid perl dictum sit, altum viditur.
Re: Using DBI handle in several packages
by merlyn (Sage) on Jun 03, 2001 at 20:40 UTC
    If they're sharing the same DB handle, then they probably are doing similar things to the database. In that case, create a DB "manager" class that holds the DB handle as a package or lexical var, and then exports routines of choice to the modules that need them. You can also do lazy initialization of the connection that way, since you'll know the state.

    I think I gave this solution about a year ago here before. {grin}

    -- Randal L. Schwartz, Perl hacker