2010-12-26 13 views
2

Ich habe ein Perl-Skript, in dem ich eine Tabelle aus den vorhandenen MySQL-Datenbanken erstellen. Ich habe Hunderte von Datenbanken und Tabellen in jeder Datenbank enthält Millionen von Datensätzen, aus diesem Grund dauert Abfrage manchmal wegen Problemen mit der Indizierung, und manchmal habe ich Speicherplatz aufgrund von fehlerhaften Joins. Gibt es eine Möglichkeit, die Abfrage im selben Skript zu beenden und auf Speicherverbrauch und Ausführungszeit zu warten?Kill mysql Abfrage in Perl

P.S. Ich benutze DBI-Modul in Perl für MySQL-Schnittstelle

+0

Ist ['kill'] (http://dev.mysql.com/doc/refman/5.0/de/kill.html) nützlich? – ajreal

Antwort

2

Ich benutzte Befehl KILL QUERY wie in http://www.perlmonks.org/?node_id=885620 beschrieben

Dies ist der Code von meinem Skript

eval { 
    eval { # Time out and interrupt work 
     my $TimeOut=Sys::SigAction::set_sig_handler('ALRM',sub { 
      $dbh->clone()->do("KILL QUERY ".$dbh->{"mysql_thread_id"}); 
      die "TIMEOUT\n"; 
     }); 
     #Set alarm 
     alarm($seconds); 
     $sth->execute(); 
     # Clear alarm 
     #alarm(0); 
    }; 
    # Prevent race condition 
    alarm(0); 
    die "[email protected]" if [email protected]; 
}; 

Dieser Code die Abfrage tötet und auch alle temporären Tabellen

1

Soweit Ausführungszeit, verwenden Sie alarm Perl-Funktionality zu Timeout.

Ihr ALRM Griff kann entweder die (siehe Beispiel unten), oder geben Sie einen DBI cancel Anruf (sub { $sth->cancel };)

Die DBI documentation hat eigentlich eine sehr gute Diskussion über diese sowie Beispiele:

eval { 
    local $SIG{ALRM} = sub { die "TIMEOUT\n" }; # N.B. \n required 
    eval { 
     alarm($seconds); 
     ... code to execute with timeout here (which may die) ... 
    }; 
    # outer eval catches alarm that might fire JUST before this alarm(0) 
    alarm(0); # cancel alarm (if code ran fast) 
    die "[email protected]" if [email protected]; 
    }; 
    if ([email protected] eq "TIMEOUT\n") { ... } 
    elsif ([email protected]) { ... } # some other error 

Für die Suche nach Speicher benötigen Sie nur für den ALRM-Handler - anstatt einfach zu löschen/abzubrechen - überprüft zuerst den Speicherverbrauch Ihres Skripts.

Ich werde nicht ins Detail gehen, wie Speicherverbrauch zu messen, da es sich um eine unabhängige Frage ist, die wahrscheinlich bereits beantwortet umfassend über SO war, aber man kann size() Methode von Proc::ProcessTableas described in the Perlmonks snippet Find memory usage of perl program verwenden.

1

Watch out entfernt, dass Sie können eine Abfrage nicht mit demselben Verbindungshandler beenden, wenn Sie eine Abfrage haben, die wegen einer Tabellensperre blockiert ist. Sie müssen eine weitere Verbindung mit demselben Benutzer öffnen, und diese Thread-ID wird angezeigt.

Natürlich müssen Sie die Liste der aktuell geöffneten Thread-IDs in einem Hash speichern.

Beachten Sie, dass der Rest des Perl-Codes ausgeführt wird, sobald Sie eine Thread-ID beendet haben.