perl SpeedyCGIでデータベースの接続を永続化する

perl SpeedyCGIでデータベースの接続を永続化する

perlスクリプトをSpeedyCGIスクリプトとして動作させる場合、グローバル変数の値は保持され続ける。なので、一度接続したデータベースハンドルを使い回すことでデータベースへの接続コストを削減できる。

テスト用スクリプト

#!/usr/bin/speedy

use strict;
use warnings;
use DBI;

#DB用設定
my $db_user = 'db_user_name';
my $db_pass = 'db_password';
my $db_name = 'db_name';
my $db_host = 'localhost';
my $dbi = "DBI:mysql:$db_name:$db_host";

# テスト用
print "content-type:text/html;\n\n";
our $c;
$c=1 if !$c;
print "($c回目)\n";
$c++;

our $dbh;    # データベースハンドルは our でグローバル変数を宣言する必要がある。
my  $db_connect_flag;

# $dbhがある場合データベースハンドルが有効かチェック
eval{
    $db_connect_flag = $dbh->ping;
    print "DB check.\n";  # 2回目以降はチェック(テスト用)
} if defined($dbh);

# 未接続ならDBに接続する
if(!$db_connect_flag){
    eval {
        $dbh = DBI->connect($dbi, $db_user, $db_pass)|| die $dbh->errstr;
    };
    # 接続エラーならエラー処理
    error("DB could not connect.")  if $@;
    print "DB conect OK.\n";   # 初回は接続(テスト用)
}
exit;

ポイントとしては our $dbh; としてグローバル変数宣言する事。my でレキシカル変数を宣言してしまうと毎回初期化されてしまう。

defined で $dbh が定義済みか調べて、定義済みなら ping を送って有効か調べる。無効ならデータベースへ接続する。

必要な部分はこんな感じ。

our $dbh;
my  $db_connect_flag;

# $dbhがある場合データベースハンドルが有効かチェック
eval{ $db_connect_flag = $dbh->ping; } if defined($dbh);

# 未接続ならDBに接続する
if(!$db_connect_flag){
    eval {
        $dbh = DBI->connect($dbi, $db_user, $db_pass) || die $dbh->errstr;
    };
    # 接続エラーならエラー処理
    error("DB could not connect.")  if $@;
}

あくまでSpeedyCGIでのスクリプトで、FastCGIの場合とかは違うかも。