重启多线程perl脚本并关闭mysql连接

时间:2009-12-02 21:00:45

标签: mysql database multithreading perl restart

我有一个Perl脚本,它读取命令文件并在必要时通过执行以下操作重新启动:

myscript.pl:

exec '/home/foo/bin/myscript.pl';
exit(0);

现在,除了一个问题,这个工作正常。读取命令文件的线程无法访问我使用的DBI句柄。经过多次重启,我似乎建立了开放的mysql连接数,直到我遇到可怕的“Too Many Connections”错误。 DBI规范说:

“由于这个(可能是临时的)限制,新创建的线程必须与数据库建立自己的连接。不能跨线程共享句柄。”

是否可以通过任何方式关闭连接或以其他方式重新启动脚本?

3 个答案:

答案 0 :(得分:2)

使用线程之间共享的标志变量。让命令行读取线程将标志设置为退出,持有DB句柄的线程释放它并实际执行重新执行:

#!/usr/bin/perl

use threads;
use threads::shared;

use strict; use warnings;
my $EXIT_FLAG :shared;

my $db_thread = threads->create('do_the_db_thing');
$db_thread->detach;

while ( 1 ) {
    sleep rand 10;
    $EXIT_FLAG = 1 if 0.05 > rand or time - $^T > 20;
}

sub do_the_db_thing {
    until ( $EXIT_FLAG ) {
        warn sprintf "%d: Working with the db\n", time - $^T;
        sleep rand 5;
    }
    # $dbh->disconnect; # here
    warn "Exit flag is set ... restarting\n";
    exec 'j.pl';
}

答案 1 :(得分:2)

您可以尝试注册atexit函数以在打开它时关闭DBI句柄,然后使用fork& exec重启脚本而不是exec。然后父进程调用exit,调用atexit回调来关闭DBI句柄。孩子可以正常地重新执行。

编辑:在考虑了几分钟之后,我相信你可以完全跳过atexit因为句柄会在父母退出时自动关闭。当然,除非在关闭DB句柄时需要执行比简单文件句柄关闭更复杂的操作。

my $pid = fork();
if (not defined $pid) {
    #Could not fork, so handle the error somehow
} elsif ($pid == 0) {
    #Child re-execs itself
    exec '/home/foo/bin/myscript.pl';
} else {
    #Parent exits
    exit(0);
}

答案 2 :(得分:2)

如果您期望有很多连接,您可能希望DBI::Gofer充当您的DBI代理。您可以在任意数量的脚本中创建任意数量的连接,DBI :: Gofer会尽可能地共享它们。