2009-07-28 22 views
5

私はPerl fork managerとDBIを試しました。 しかし、エラーが発生しましたDBD :: mysql :: stの実行に失敗しました:クエリ中にMySQLサーバーへの接続が失われました。ここでPerlの分岐した子からデータベースを照会できないのはなぜですか?

サンプルコード:私は高い値に低いとのクエリ(私はint型の10Kレコードをスピッティングしている)

use Parallel::ForkManager; 
my $pm = new Parallel::ForkManager(50); 
my $db = krish::DB->new or die $!; # its has all connection details 
while ($low < $high ) { 
    # Some value manipulation 

    my $pid = $pm->start and next; 
    #db_execution returns execution 
    while (my $sth = db_execution ($db, $low , $high)) { 
     ... 
     #fetch row operation 
     ... 
    } 
    $pm->finish; 
} 

sub db_execution { 
    ... 
    my $dbh = $db->connect('students') or die $!; 
    my $sth = $dbh->prepare($sql) or die "$!:" . $dbh->errstr; 
    $sth->execute or die "$!:" . $sth->errstr; 
    ... 
} 

同じコードが出て並列処理で実行されていることを確認します。どうした? 解決方法これはですか?

+0

すみません。私は誤ってコミュニティのwikiに変換しました – joe

答えて

9

プロセス間でデータベース接続を共有する場合(フォークを使用している場合)、あるプロセスが他のプロセスの下からそれを閉じないようにする必要があります。接続も変数であるため、Perlインタープリタがシャットダウンすると、そのオブジェクトのDESTROYメソッドが呼び出されます。この場合、この場合は接続が閉じられます。

したがって、子プロセスが終了してシャットダウンしたときに子プロセスが終了すると、プロセスは親プロセスのプロセスから終了します。これを防ぐ方法は、フォークの前に親プロセスでInactiveDestroyをtrueに設定し、完了したら親で明示的に接続を閉じることです。

https://metacpan.org/pod/DBI#InactiveDestroy

+3

もう一つの方法は 'fork()'の後にデータベース接続を開くことです。そうすれば、それぞれの子供は自分自身のつながりを持ち、互いに干渉することはできません。複数のプロセス間で単一の接続を共有することは、通常はお勧めできません。 –

+1

ええ、それも動作します。特に、Oracleなどの一部のシステムでは、プロセス間の共有の共有がサポートされていないためです。 – mpeters

0

あなたはすべての子プロセスで同時に同じDBハンドルを使用してトラブルを求めています。それぞれの子に新しい接続を作成する必要があります。

心配しないでください...私はコードの残りの部分を読んでいます。

関連する問題