2017-07-18 3 views
2

Ich benutze Apache2.2 (Arbeiter)/mod_perl 2.0.4/Apache :: DBI/CGI :: Session und Firebird RDBMS.DBI zwischengespeicherten Anweisungen gegangen und CGI :: Sitzung ist stecken geblieben

Ich schrieb auch CGI :: Session :: Driver :: firebird.pm, um mit Firebird RDBMS zu arbeiten. DB-Verbindung wird von Apache :: DBI gebündelt und gibt Verbindungshandle zu CGI :: Session {Handle => $ dbh}.

Die Nummer der DB-Verbindung entspricht der Anzahl der Worker-Prozesse.

Ich postete Programming with Apache::DBI and firebird. Get Stucked httpd on exception 3 Monat. Ich habe einen Grund für dieses Problem gefunden und möchte wissen, wie ich es beheben kann.

$dbh = DBI->connect("dbi:Firebird:db=$DBSERVER:/home/cdbs/xxnet.fdb; 
ib_charset=UTF8;ib_dialect=3",$DBUSER,$DBPASS,{ 
    AutoCommit=>1, 
    LongReadLen=>8192, 
    RaiseError=>1 
}); 
my $session = new CGI::Session('dbi:firebird',$sessid,{Handle=>$dbh}); 
my $ses_p1 = $session->param('p1'); 

eval { $dbh->begin_work() 

    my $sql = "SELECT * FROM SAMPLETABLE" 
    my $st = $dbh->prepare($sql); 
    $st->execute(); 
    while (my $R = $st->fetchrow_hashref()) { 
    ... 
    } 
    $st->finish(); 
}; warn [email protected] if [email protected]; 
if ([email protected]) { 
    $dbh->rollback(); 
}else{ 
    $dbh->commit(); 
} 
$session->flush(); 

wenn eine SQL-Fehler aufgetreten ist, fängt ein eval Block Ausnahme und Rollback-Transaktion. Danach ruft CGI :: Session das Sitzungsobjekt nicht mehr ab.

Da die prepare_cached-Anweisung bei CGI :: Session :: DBI.pm fehlschlägt. CGI :: Session :: DBI.pm verwenden prepare_cached ($ sql, undef, 3). '3' ist der sicherste Weg, eine zwischengespeicherte Anweisung zu verwenden, aber in dieser Situation findet sie niemals eine fehlerhafte Anweisung.

Wie behebt man das? Anforderung erhöhen, um CGI :: Session :: DBI.pm zu ändern, um prepare() -Anweisung zu verwenden? write store(), retrieve(), traverse() Funktion in firebird.pm Prepare() Anweisung zu verwenden?

Es kann andere prepare_cached() gehen nach Fang Ausnahme scheitern ...


1) I auf CGI-Chip-Anweisung hinzufügen :: Session-> errstr() ich einen Fehler bekam „neue (): failed: load(): Daten konnte nicht abgerufen werden: retrieve(): $ sth-> Ausführen fehlgeschlagen mit Fehlermeldung " 2) Ich lege das Session-Objekt nach Sitzung-> load() wenn $ Sitzung gültig ist, ändert sich sind in der DB gespeichert. 3) Ich ersetze begin_work() zu {AutoCommit} = 0 Ergebnisse sind gleich. Ich kann $ dbh normalerweise nach Abfangen von Ausnahme und Rollback verwenden, aber neue CGI :: Session gibt Fehler zurück. ------------------------------------------ hinzugefügt am 2017/07/26 18 : 47 JST

Bitte geben Sie mir Ihren Vorschlag.

Vielen Dank.

+0

vielleicht 'Session-> Flush' kills Sitzung? vielleicht soll man irgendeinen Wert von '$ sessid' entfernen? –

+0

$ session-> flush() löst keine Ausnahmen aus. Nach $ session-> flush() funktioniert eine andere Abfrage gut, aber nächste "neue CGI :: Session()" gibt leer zurück. CGI :: Session-> load() gibt undef zurück. –

+0

Ich testete es auch durch Entfernen von $ session-> flush(), aber nächste CGI: Sitzung leer zurückgegeben. –

Antwort

2

Es gibt verschiedene Dinge, die Sie vor der Anforderung Änderungen an CGI versuchen könnten :: Session :: Treiber :: DBI.pm ...

Zuerst die Art und Weise new CGI::Session aufgerufen, um zu diagnostizieren, wenn das Problem auftritt wenn die Sitzung erstellt oder geladen:

my $session = CGI::Session->new('dbi:firebird',$sessid,{Handle=>$dbh}) or die CGI::Session->errstr(); 

die Methoden param oder delete speichert Änderungen an der Sitzung innerhalb $session Griff, nicht in DB. flush speichert in der Datenbank die Änderungen, die im Sitzungshandle vorgenommen wurden. Verwenden Sie $session->flush() erst nach einer Session-> param setzen/Update oder einer Sitzung löschen:

$session->param('p1','someParamValue'); 
$session->flush() or die 'Unable to update session storage!'; 

# OR 
$session->delete(); 
$session->flush() or die 'Unable to update session storage!'; 

Verfahren flush nicht $session Griff nicht zerstört (Sie noch $session->param('p1') nach dem Flush aufrufen können).In einigen Fällen speichert mod_perl $session, was beim nächsten Versuch, dieselbe Sitzung zu laden, Probleme verursacht. In diesen Fällen muss sie zerstört werden, wenn es nicht mehr gebraucht wird:

undef($session) 

Das letzte, was ich vorschlagen kann, ist begin_work Methode vermeiden Sie, das Transaktionsverhalten statt mit AutoCommit steuern (weil die DBD::Firebird documentation sagt, das ist die Art und Weise Transaktionen sollten gesteuert werden) und commit innerhalb des eval-Block:

eval { 
    # Setting AutoCommit to 0 enables transaction behavior 
    $dbh->{AutoCommit} = 0; 

    my $sql = "SELECT * FROM SAMPLETABLE" 
    my $st = $dbh->prepare($sql); 
    $st->execute(); 

    while (my $R = $st->fetchrow_hashref()) { 
     ... 
     } 

    $st->finish(); 
    $dbh->commit(); 
    }; 
if ([email protected]) { 
    warn "Tansaction aborted! [email protected]"; 
    $dbh->rollback(); 
    } 

# Remember to set AutoCommit to 1 after the eval 
$dbh->{AutoCommit} = 1; 

Sie sagten, Sie Ihre eigenen Session-Treiber für Firebird geschrieben ... Sie sollten sehen, wie die CGI/Treiber/sqlite.pm oder CGI/Treiber/mysql.pm gemacht werden, vielleicht müssen Sie einige holende Methode y schreiben Ou fehlen ...

Hoffe das hilft !!

+0

1) add die CGI :: Sitzung-> errstr(): new(): fehlgeschlagen: load(): konnte Daten nicht abrufen: retrieve(): $ sth-> Ausführen fehlgeschlagen mit Fehlermeldung 2) Spülung Sitzung Objekt: Wenn $ Session gültig ist, werden Änderungen in der DB gespeichert. 3) verwende {AutoCommit} = 0 und andere: Situation ist gleich. Ich kann $ dbh normalerweise nach Abfangen von Ausnahme und Rollback verwenden, aber neue CGI :: Session gibt Fehler zurück. --- Mein Treiber/firebird.pm hat nur init() und table_name(), dann verwenden Sie speichern/abrufen in DBI.pm. Ich habe firebird.pm geschrieben, um DBD :: Firebird zu laden und DSN als 'dbi: firebird' zu machen. –

+0

Ich füge Speicher hinzu, retrieve, traverse ohne "_cached" zu firebird.pm. Es sieht gut aus. mysql.pm hat mk_dsn, init, Tabellenname, speichern. store() wird geändert, um 'ON DUPLICATES' von DBI.pm zu verwenden. DBI-> begin_work() ändert {AutoCommit} zu 0. Ich habe Problemumgehungen gefunden. Also, ich möchte wissen, warum Cache-Anweisungen weg sind? –

+0

Können Sie Ihre Frage mit den gefundenen Fehlern aktualisieren? – kidkamek

Verwandte Themen