2010 Perl Advent Calendar などでも説明していた Scope::Container でDBの接続管理を行うモジュールを書いた。

CPAN: http://search.cpan.org/dist/Scope-Container-DBI/ github: https://github.com/kazeburo/Scope-Container-DBI

機能的には、Scope::Container に接続情報をキャッシュして、同じDSN・ユーザ名で接続の場合、キャッシュからdbhを返します。Scope::Containerなので任意のスコープで接続の維持と切断ができます。

Scope::Container::DBIには、connectメソッドがあるだけ。DBIと同じくdsn、ユーザ名、パスワード、オプションを渡す。

use Scope::Container::DBI;
use Scope::Container;

sub work {
    my $contaier = start_scope_container();      
    for (1..n) {
        # 最初の1回だけ接続。あとはキャッシュされる  
        my $dbh = Scope::Container::DBI->connect(
            'dbi:mysql:mydb;host=myhost', 'myuser', 'mypasswd',
            { RaiseError => 1, mysql_connect_timeout => 4, mysql_enable_utf8 => 1 }
        );
    }
    #$contaierが破棄されるまで接続はキャッシュ
}

Plack::Middleware::ScopeContaierと組み合わせると、1リクエスト中だけ永続接続が簡単に実現できます。

あと、複数のdsnをarrayrefで渡すと、その中からランダムで選び出して接続をすることもできます。slaveを並べる場合などに使えます。

use Scope::Container::DBI;
use Scope::Container;

my $dbh = Scope::Container::DBI->connect(
    ['dbi:mysql:mydb;host=myslave01', 'myuser', 'mypasswd', {..}],
    ['dbi:mysql:mydb;host=myslave02', 'myuser', 'mypasswd', {..}],
    ['dbi:mysql:mydb;host=myslave03', 'myuser', 'mypasswd', {..}],
);

これも接続をキャッシュして1回だけ接続が行われます。

あと、Scope::Container::DBIでキャッシュのdbhを再利用する場合にはDBIx::Connectorのように、プロセスID/スレッドIDを確認しているので、fork safeです。

MySQLの文字コードの設定など接続が完了した時点でなんらかのアクションをしたいことがあると思います。Scope::Container::DBIにはその機能はありませんが、DBI標準のCallbackが使えます。

my $dbh = Scope::Container::DBI->connect($dsn, $username, $password, {
    RaiseError => 1,
    Callbacks  => {
        connected => sub {
            shift->do(q{SET NAMES utf8});
        },
    },
});

ちょっと長くなるけど使えるはず

おためしくださいませませ

このブログ記事について

このページは、Masahiro Naganoが2011年3月23日 13:01に書いたブログ記事です。

ひとつ前のブログ記事は「3.11 新宿から横浜まで歩いて帰ってきた」です。

次のブログ記事は「Nagios 統合監視 [実践] リファレンス を献本頂きました」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja