Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie gehe ich richtig mit InnoDB-Deadlocks in Java/JDBC um?

Ihr Code ist im Wesentlichen richtig. Die Ausnahme, die ausgelöst wird, wenn ein Deadlock auftritt, ist eine SQLException . getSQLState() der Ausnahme Die Methode stellt einen Fehlercode bereit, der zusätzliche Informationen über den eigentlichen Fehler.

Sie sollten auch zwischen den Versuchen eine kurze Zeit warten, um Ihren Server nicht zu sehr zu belasten.

Wie Sie klug erraten haben, legen Sie eine maximale Anzahl von Versuchen fest, oder Sie landen möglicherweise in einer Endlosschleife.

Der endgültige Code könnte so aussehen:

boolean oops;
int retries = 5;
Connection c = null;
Statement s = null;
ResultSet rs = null;    

do
{
    oops = false;
    c = null;
    s = null;
    rs = null;
    try
    {
        c = openConnection();
        s = c.createStatement();
        rs = s.executeQuery("SELECT stuff FROM mytable");
        fiddleWith(rs);
    }
    catch (SQLException sqlex)
    {
        oops = true;
        switch(sqlex.getErrorCode()())
        {
            case MysqlErrorNumbers.ER_LOCK_DEADLOCK:
                // deadlock or lock-wait time-out occured
                break;
            ...
        }
        Thread.sleep(1000); // short delay before retry
    }
    finally
    {
        if (rs != null) try {
            rs.close();
        } catch (SQLException e) {
            // some error handler here
        }

        if (s != null) try {
            s.close();
        } catch (SQLException e) {
            // some error handler here
        }

        if (c != null) try {
            c.close();
        } catch (SQLException e) {
            // some error handler here
        }

    }
}
while (oops == true && retries-- > 0);

Offensichtlich ist der obige Code suboptimal. Möglicherweise möchten Sie zwischen Fehlern, die zur Verbindungszeit auftreten, und Fehlern zur Ausführungszeit unterscheiden. Sie könnten auch feststellen, dass nach einigen Fehlern wenig Hoffnung besteht, dass ein weiterer Versuch funktioniert (z. B. falsche Anmeldeinformationen oder SQL-Syntaxfehler).

Sie haben viele Fragen gestellt, aber ich werde versuchen, sie alle zu beantworten:

Ja, siehe oben:SQLException 's sind diejenigen, bei denen weitere Informationen von getErrorCode() bereitgestellt werden oder getSQLState() .

Eine SQLException könnte von praktisch allen Methoden aller Klassen aus der java.sql geworfen werden Paket.

Ja, siehe oben.

Natürlich dürfen Sie ein PreparedStatement nicht neu erstellen zwischen zwei Abfragen. Sie müssen nur neue Werte für Ihre Parameter festlegen, bevor Sie executeQuery() aufrufen wieder. Natürlich, wenn Sie eine weitere Abfrage ausführen müssen, dann ein neues PreparedStatement ist erforderlich.

Ein (neues) ResultSet Objekt wird von Statement.executeQuery() zurückgegeben , das das Ergebnis der Abfrage darstellt. Sie erstellen niemals selbst ein solches Objekt. Idealerweise rufen Sie ResultSet.close() auf so schnell wie möglich Speicher freizugeben.

Ich rate Ihnen dringend, dem zweiten Kapitel dieses Tutorials zu folgen ("SQL-Anweisungen verarbeiten").