Изящная обработка Perl-критических ошибок DBD :: ODBC - PullRequest
2 голосов
/ 29 декабря 2011

У меня есть простой 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 оказывается ненужным и нуждается в повторной инициализации?

1 Ответ

1 голос
/ 29 декабря 2011

Проблема вызвана тем, что, хотя execute () не выполняется, вы все равно вызываете commit ().Поскольку соединение отсутствует, вы не можете отправить в БД вызов коммита.Кроме того, похоже, что у вас включен AutoCommit, поэтому БД пытается закрыть все открытые транзакции при удалении соединения в вызове DESTROY.

Вы можете попробовать что-то вроде этого (простите мой ржавый perl):

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...