2011-12-28 3 views
2

네트워크 포트에서 수신하고 데이터를 받아들이고 DBD :: ODBC를 사용하여 데이터를 저장하는 간단한 Perl 스크립트가 있습니다. 다음과 같이 보입니다.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: [email protected]"); 
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. 
난 그냥 일정 시간 동안 대기에 의해 하나, 실패의이 종류에 resiliant 될 수있는 스크립트를 원한다면

및 데이터베이스가 다시 깨어 났는지 확인하거나 수신 된 데이터를 삭제하고 소켓에서 더 많은 데이터를 가져 오는 경우 가장 좋은 방법은 무엇입니까? 위의 오류는 $ dbh가 정크로 끝나고 다시 초기화 될 필요가 있다는 것을 의미합니까?

답변

1

이 문제는 execute()가 실패하더라도 여전히 commit()을 호출하고 있기 때문에 발생합니다. 연결이 없으므로 커밋 호출을 DB로 보낼 ​​수 없습니다. 또한 DESTROY 호출에서 연결을 삭제할 때 DB가 열려있는 모든 트랜잭션을 닫으려고 AutoCommit이 실행 된 것처럼 보입니다.

당신이 뭔가 (내 녹슨 펄을 용서)을 시도 할 수 : 그냥 부를 수

내가 루프를 종료하지만, DB가 다시 계속하기 전에 오기를 단지 잠시 기다릴 싶었다면
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); 
+0

을, 잠 좀 자니? 또한,'execute' 명령으로'$ msg'가 자동으로 채워지나요? – growse

+0

종료하지 않으려면 새 연결을 만들어야합니다. 'break'를'DBI-> connect()'에 대한 새로운 호출로 대체하십시오. 네트워크 메시지를 삭제하지 않도록 재 시도를 지원하도록 루프를 재구성해야합니다. – saarp

+0

나는 그 생각에 감사하지만 실제로 네트워크 트래픽을 포기하는 것에 대해서는 소란스럽지 않습니다. 나는 가서 내가 찾을 수있는 것을 보게 될 것이다. – growse

관련 문제