sql >> Database >  >> RDS >> Mysql

Hoe om te gaan met InnoDB-deadlocks in Java/JDBC?

Je code is in wezen correct. De uitzondering die optreedt wanneer een dead lock optreedt, is een SQLException . De uitzondering is getSQLState() method levert een foutcode op die aanvullende informatie over de daadwerkelijke fout.

Je moet ook een korte tijd wachten tussen de pogingen, om je server niet te veel te belasten.

Zoals je slim geraden hebt, stel een maximum aantal pogingen in, anders zou je in een oneindige lus terecht kunnen komen.

De uiteindelijke code kan er als volgt uitzien:

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);

Het is duidelijk dat de bovenstaande code suboptimaal is. Mogelijk wilt u een onderscheid maken tussen fouten die optreden tijdens de verbinding en fouten tijdens de uitvoering. U kunt ook ontdekken dat er na enkele fouten weinig hoop is dat een nieuwe poging zal werken (bijv. verkeerde inloggegevens of SQL-syntaxisfout).

Je hebt veel vragen gesteld, maar ik zal proberen ze allemaal te beantwoorden:

Ja, zie hierboven:SQLException 's zijn degenen, met meer informatie geleverd door getErrorCode() of getSQLState() .

Een SQLException kan worden gegenereerd door vrijwel alle methoden van alle klassen uit de java.sql pakket.

Ja, zie hierboven.

Het is duidelijk dat u een PreparedStatement niet opnieuw moet maken tussen twee vragen. U hoeft alleen nieuwe waarden in uw parameters in te stellen voordat u executeQuery() aanroept nog een keer. Natuurlijk, als u nog een zoekopdracht moet uitvoeren, dan een nieuwe PreparedStatement is vereist.

Een (nieuwe) ResultSet object wordt geretourneerd door Statement.executeQuery() , die het resultaat van de query vertegenwoordigt. Zo'n object maak je nooit zelf. In het ideale geval roept u ResultSet.close() . aan om het geheugen zo snel mogelijk vrij te maken.

Ik raad je ten zeerste aan om het tweede hoofdstuk van deze tutorial te volgen ("SQL-statements verwerken").




  1. MySQL afstemmen voor snelle creatie van kolommen/indexen tijdens ontwikkeling

  2. Drie tabellen samenvoegen met MySQL

  3. Sequelize:meerdere waar clausule

  4. Django kan MySQLdb python-module niet vinden