Wie timeout "select for update" in Oracle mittels Perl / DBI

gibt es einen einfachen Weg, um timeout eine SQL-Anweisung so, dass es scheitern wird, anstatt zu warten, (z.B. liefert ein leeres ResultSet oder eine Fehlermeldung oder was auch immer), so kann ich lassen Sie einen job Ressourcenreservierung scheitern und geben anderen eine chance? Ich bin auf der Suche für einige DBI option habe ich übersehen, so weit; Versand SIGALRMs mir, Selbstmord zu Begehen, ist eher nicht das, was ich im Sinn haben (auch wenn ich vielleicht zu dem Mittel greifen müssen, dass, wenn ich musste).

Den code snipped ist pseudo-niert und verkürzt, um die extreme, aber ich hoffe, Sie fangen die drift.

my $sql = "SELECT one, two, three FROM sometable WHERE this = ? AND that = ?";
my $sth = $self->make_handle( $sql );
eval {
    foreach my $this ( sort keys %needed_ressources ) {
        # vvv This is where the idle time is spent vvv
        $sth->execute( $this, $that ) or die( "DB connection gone?!" );
        # ^^^ This is where the idle time is spent ^^^
        my ( $one, $two, $three ) = $sth->fetchrow_array();
        unless( $one ) { # undefined record set == not found
            $self->{DB_HANDLE}->rollback();
            die( "$this not defined for $that!" );
        }
    }
    # If we haven't died so far, we can move on
    foreach... #similar loop here doing the actual update statement
    $self->{DB_HANDLE}->commit();
};
return( 1 ) unless $@;
return( undef );

Hier sind die blutigen details für die interessierten:

In eine Anwendung, die Massiv-parallele numbercrunching es ist ein ressource-locking-Mechanismus implementiert, verwendet eine oracle-Tabelle. Jeder Auftrag Bedarf zu sperren, die eine Reihe von Ressourcen für das Lesen und/oder eine Anzahl von Ressourcen für Sie zu schreiben, und kann nur gestartet werden, wenn alle locks erworben wurden, erfolgreich. Anstatt geduldig darauf warten, dass Ressourcen freigegeben werden, die Arbeitsplätze sollten nur scheitern und re-führen Sie später von Ihrem Meister (so bleibt die Anzahl der offenen Transaktionen niedrig, während die Steigerung der performance durch mehr jobs um, die tatsächlich crunch).

Natürlich, bevor Sie tatsächlich die Tabelle zu aktualisieren, jede Zeile ist reserviert mit einem "SELECT ... FOR UPDATE" - Anweisung, so Oracle verwendet row level locking und Transaktionen gleichzeitig geschehen kann, auf den Tisch. Zur weiteren Verringerung der möglichen race-conditions und deadlocks alle jobs wählen Sie zuerst Ihre ressource Zeilen und dann Zeile sperren Sie Sie unter Verwendung der gleichen Anordnung vor Durchführung der Aktualisierung.

Als von der aktuellen Implementierung funktioniert in die meisten der Fälle. Aber, da die "Select for update" blockiert solange, bis Oracle tatsächlich gewährt die Zeile sperren, kann es immer noch passieren, dass ein Auftrag im Leerlauf und wartet auf seine Ressourcen, und ich bin, nachdem diese eine bessere Nutzung der verfügbaren CPU-Leistung. Es ist OK zu warten Sie eine Sekunde oder zwei, aber nicht zehn oder mehr nur für die Verriegelung. Für unlocking später, warten erforderlich ist, natürlich, also die Einstellung der ganzen DB-Verbindung zu akzeptieren nur sofortige Ergebnisse wird nicht funktionieren.

Ich bin immer dankbar für RTFM Antworten, solange Sie auf die Stelle in der M, dass ich TF haben R ;-))

Vielen Dank im Voraus,

Olfan

  • Was meinst du mit "Selbstmord"? Sie können festlegen, dass Ihr SIGALRM-handler zu tun, was Sie wollen. Sind Sie gerade versuchen zu vermeiden, die Signale zusammen?
  • Ich bin stark versucht zu haben, nur der master-Prozess den Umgang mit Signalen. Vielleicht Perl kann eigentlich damit umgehen, aber meine innere Struktur des Gehirns ist noch nicht bereit, um unterschiedliche signal-handlings in beiden Vater-und Kind-Prozesse.
InformationsquelleAutor Olfan | 2009-06-08
Schreibe einen Kommentar