优雅地处理Perl关键DBD::ODBC错误

优雅地处理Perl关键DBD::ODBC错误,perl,exception-handling,odbc,Perl,Exception Handling,Odbc,我有一个简单的Perl脚本,它监听网络端口,接受数据并使用DBD::ODBC将内容写入数据库。它看起来有点像这样: #!/usr/bin/perl my $dbh = DBI->connect('dbi:ODBC:SqlProd',"yay","ooo",{AutoCommit => 0}) || die "Couldn't connect to db"; my $sth = $dbh->prepare("insert into table some stuff"); $so

我有一个简单的Perl脚本,它监听网络端口,接受数据并使用DBD::ODBC将内容写入数据库。它看起来有点像这样:

#!/usr/bin/perl
my $dbh = DBI->connect('dbi:ODBC:SqlProd',"yay","ooo",{AutoCommit => 0}) || die "Couldn't connect to db";
my $sth = $dbh->prepare("insert into table some stuff");

$sock = IO::Socket::INET->new(LocalPort => '1234', Proto => 'udp')||die("Socket: $@");
do {
    $sock->recv($buf, $MAXLEN);

    /*parse some data here*/
    /*bind some parameters to $sth here*/

    my $rv = $sth->execute() || warn logit('warning', "Error inserting to db: $! $msg");
    $dbh->commit() || warn logit('err',"Error committing db transaction: $! $msg");

}while(1);
这虽然有点粗糙,但效果相当不错。但是,由于未知原因,数据库关闭,脚本崩溃,例如:

DBD::ODBC::st execute failed: [unixODBC][FreeTDS][SQL Server]Write to the server failed     (SQL-08S01) at /usr/local/bin/haproxy-syslog line 117.
0 at /usr/local/bin/haproxy-syslog line 117.
DBD::ODBC::db commit failed: [unixODBC][FreeTDS][SQL Server]Could not perform COMMIT or     ROLLBACK (SQL-HY000) at /usr/local/bin/haproxy-syslog line 118.
Error committing db transaction: Connection reset by peer 
DBD::ODBC::db DESTROY failed: [unixODBC][FreeTDS][SQL Server]Could not perform COMMIT or ROLLBACK (SQL-HY000) during global destruction.

如果我希望脚本能够适应这种失败,或者只是等待一段时间,看看数据库是否再次唤醒,或者删除接收到的数据并从套接字中提取更多数据,那么最好的方法是什么?上述错误是否意味着$dbh最终成为垃圾并需要重新初始化?

导致此问题的原因是,即使execute()失败,您仍在调用commit()。由于没有连接,因此无法向DB发送提交调用。此外,您似乎已启用自动提交,以便DB在销毁调用中处理连接时尝试关闭任何打开的事务

您可以尝试这样的方法(请原谅我生疏的perl):


如果我不想退出循环,而只是在继续之前等待DB返回,我可以调用
sleep
?另外,
execute
命令是否自动填充了
$msg
?如果不想退出,则必须创建一个新连接。用对
DBI->connect()
的新调用替换
break
。你将不得不重新构造你的循环以支持重试,这样你就不会丢弃网络消息。事实上,我并不担心丢弃网络流量,尽管我很欣赏这个想法。我去看看能找到什么。
do {
    $sock->recv($buf, $MAXLEN);

    # parse some data here
    # bind some parameters to $sth here

    my $rv = $sth->execute() || warn logit('warning', "Error inserting to db: $! $msg");
    if ($msg ~= /connection reset/i)
    {
        warn logit('warning', "Connection disconnected.");
        $sth->disconnect();
        break; # exit while
    }
    $dbh->commit() || warn logit('err',"Error committing db transaction: $! $msg");

}while(1);