MySQL Verbindung mit mysqlPP prüfen
Andreas
- perl
Hi,
ich habe einen Daemon mit Perl geschrieben, der zur Laufzeit dynamisch eine MySQL Verbindung auf- und abbaut - je nach dem, ob MySQL gebraucht wird oder eben länger nicht mehr gebraucht wird. Im Sub zum Herstellen der Verbindung zum MySQL Server möchte ich eine Prüfung einbinden, ob bereits eine Verbindung besteht - das habe ich mit folgenden Methoden versucht ("true", wenn eine Verbindung besteht):
a) if($mysql)...
b) if(!$mysql->err)...
c) if($mysql->ping)...
d) if($mysql->{Active})...
Methode d) funktioniert mit DBD::mysql prima, aber überhaupt nicht mit DBD::mysqlPP. DBD::mysql kann ich aus kompatibilitätsgründen leider nicht verwenden und alle anderen Methoden versagen kläglich, weil a) nur in Ausnahmefällen "false" ist und b) und c) mit "die" abbrechen, wenn keine Verbindung besteht: Perl meckert (zurecht) weil das Handle $mysql eben leider nicht existiert und somit auch die Methoden "err" bzw. "ping" nicht existieren. Auch mit "eval" habe ich das schon versucht, aber Perl killt ohne Gnaden...
Weiss vielleicht jemand eine Möglichkeit, wie ich das mit DBD::mysqlPP lösen könnte? Es geht mir nur darum zu testen, ob bereits eine Verbindung zum MySQL Server besteht... Danke!
Ciao
nd
Moin!
Es geht mir nur darum zu testen, ob bereits eine Verbindung zum MySQL Server besteht... Danke!
Wie wäre es mit dem einfachen Absetzen eines Befehles: 'show databases;'.
Das funktioniert oder nicht und wirkt so wie ein "ping".
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix®
Hi,
danke für den Tipp - aber Perl killt den Prozess, sobald ich versuche eine Methode von dem nicht existierenden Handle zu verwenden:
$cmd=$mysql->prepare("SHOW DATABASES");
$cmd->execute();
$cmd->finish();
Ergebnis:
Can't call method "prepare" on an undefined value at test.pl line 574.
Und tot - das Perl Script wird gekillt.
Ciao
nd
Moin!
danke für den Tipp - aber Perl killt den Prozess, sobald ich versuche eine Methode von dem nicht existierenden Handle zu verwenden:
Hm. Kennt Perl keine Methode um genau das nicht zu tun? Es gibt doch sicher sowas eine Behandlung von exceptions /Fehlern oder?
Also etwas habe ich gefunden:
http://www.perlscripten.de/modules.php?name=News&file=article&sid=123
my $DBH = DBI->connect("DBI:$DB{driver}:$DB{name}:$DB{host}", $DB{user}, $DB{passwort}) ||
die "SQL-ERROR: connecting to MySQL-Batabase $DB{name}@$DB{host}: $DBI::errstr";
Du kannst statt die auch etwas anderes machen.
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix®
Hi,
eigentlich funktioniert die Fehlerbehandlung mit Perl recht gut - ausgenommen in diesem Fall, da komme ich einfach nicht weiter... Vielleicht bin ich auch einfach nur blind, oder so... Ich poste einfach mal ein Beispielscript, dass so im Großen und Ganzen darstellt, was passiert:
<CUT>
#!/usr/bin/perl
use DBI;
&mysql_connect();
AUFWACHEN:
if(!&mysql_check()){
&mysql_connect();
}
$cmd=$mysql->prepare("SHOW DATABASES");
$cmd->execute();
$cmd->finish();
sleep(10);
goto AUFWACHEN;
sub mysql_connect(){
my $mysql_connect_counter=0;
while(!&mysql_check()&&$mysql_connect_counter<10){
$mysql_connect_counter++;
if($mysql_connect_counter>1){
sleep(3);
}
$mysql=DBI->connect("DBI::mysqlPP:datenbank:localhost","user","pwd",{PrintError=>0,AutoCommit=>1});
}
if(!&mysql_check()){
die "Keine MySQL-Verbindung möglich: $DBI::errstr\t$!";
}
}
sub mysql_check(){
return $mysql->ping;
}
END{
$mysql->disconnect();
exit;
}
</CUT>
Knackpunkt ist hier die Funktion "mysql_check()":
Mal angenommen während "sleep(10);" wird die MySQL-Verbindung abgebaut - dann soll beim nächsten Lauf "mysql_check()" true oder false zurückgeben und bei false die Funktion "mysql_connect()" aufgerufen werden. Innerhalb von "mysql_connect()" wird zehn mal versucht die MySQL-Verbindung wieder herzustellen - klappt das nicht, wird das Script beendet.
Das Problem ist aber: Wird die MySQL Verbindung tatsächlich getrennt und "mysql_check()" aufgerufen, gibt es folgenden Fehler und das Script wird gekillt, ohne dass ich die Möglichkeit hätte mit dem Rückgabewert von "mysql_check()" was anzufangen:
Can't call method "ping" on an undefined value at test.pl line ....
Versucht habe ich das auch so:
<CUT>
sub mysql_check(){
return $mysql->{Active};
}
</CUT>
Oder so:
<CUT>
sub mysql_check(){
$cmd=$mysql->prepare("SHOW DATABASES")||return -1;
$cmd->finish();
return 1;
}
</CUT>
Das Problem ist hier, dass eben die Methode "ping" oder "prepare" zu dem Zeitpunkt, zu dem die Verbindung abgebaut wurde, nicht mehr in $mysql existiert - gibt es vielleicht eine Möglichkeit auf das Vorhandensein einer Methode zu prüfen??
Ciao
nd
Moin!
Can't call method "ping" on an undefined value at test.pl line ....
Dann teste doch vorher den Wert... Ich weiss jetzt nicht genau ob das so geht, hab länger nichts mehr mit Perl, dafür aber viel PHP gemacht...
sub mysql_check(){
if ($mysql) {
$cmd=$mysql->prepare("SHOW DATABASES")||return -1;
$cmd->finish();
return 1;
} else {
return -1;
}
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix®
Hi fastix®,
vielen Dank für Deine Tipps und Hilfen!
DBD::mysqlPP scheint DBI nicht mitzuteilen, wenn die Verbindung zum MySQL Server abgebaut wurde - das ist ein Problem, denn selbst DBD::mysqlPP erkennt nicht die Verbindungstrennung. Zuletzt (nach unendlichen Versuchen die Fehler irgendwie abzufangen - so gegen 23 Uhr...) sah meine mysql_check-Funktion dann so aus:
<CUT>
sub mysql_check(){
my $mysql_check=0;
my @mysql_check_dummy=();
if(defined($mysql)){
print "defined\n";
if($mysql->can("prepare")){
print "can prepare\n";
if(defined($cmd=$mysql->prepare("SHOW TABLES")){
print "prepare\n";
if($cmd->execute()){
print "execute\n";
if(@mysql_check_dummy=$cmd->fetchrow_array()){
print "fetchrow\n";
$cmd->finish();
$mysql_check=1;
}
}
}
}
}
return $mysql_check;
}
</CUT>
Mit "print" habe ich mir ausgeben lassen, wo sich das Script gerade befindet - und nach "print "execute\n";" ist es dann passiert. Der Fehler findet innerhalb von DBD::mysqlPP statt: Der Treiber sendet Daten an den Server ohne die Verbindung zu prüfen. Beim Versuch Daten von der nicht existierenden Verbindung zu lesen knallt's dann - ein Problem, dass ich nicht beheben kann, weil ich mysqlPP nicht ändern darf. Naja...
Also ich hab's jetzt so gelöst, dass halt jedes mal vor "sleep" die MySQL-Verbindung getrennt und nach "AUFWACHEN:" wieder aufgebaut wird. Das funktioniert, solange die Verbindung nicht irgendwo unkontrolliert unterbrochen wird - dann habe ich natürlich wieder das selbe Problem. Ich hoffe mal, dass es relativ selten vorkommen wird, dass die Verbindung einfach so weg ist...
Schade eigentlich, dass DBD::mysql auf System-C-Librarys zugreift, sonst würde ich den Treiber nehmen; Der funktioniert nämlich recht gut, scheint jedenfalls weniger Macken zu haben... Aber vielleicht schreibe ich bei Gelegenheit mal meinen eigenen Perl MySQL-Treiber DBD::mysqlPPreloaded ;o)
Ciao
nd
Moin!
Hi fastix®,
vielen Dank für Deine Tipps und Hilfen!
Naja. Perl und besonders die verschiedenen Module "hardcore" sind gar nicht unbedingt mein Thema - ich konnte Dir nur mit dem wenigen zur Seite stehen, was ich selbst meinen Seminarteilnehmern beibringe, also Grundlagenwissen. Insofern hast Du zwar Tipps bekommen, aber so die richtig fette Unterstützung konnte ich nicht liefern. War aber eine gute Idee für mich wieder mal reinzuschauen um die Syntax nicht ganz zu verlernen :(
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix®