sql >> Database teknologi >  >> RDS >> Mysql

Hvordan håndteres InnoDB-deadlocks korrekt i Java/JDBC?

Din kode er stort set korrekt. Undtagelsen, der opstår, når en dead lock opstår, er en SQLException . Undtagelsens getSQLState() metode giver returnerer en fejlkode, der giver yderligere oplysninger om selve fejlen.

Du bør også vente et kort stykke tid mellem forsøgene for ikke at belaste din server for meget.

Som du klogt gættede, så indstil et maksimalt antal forsøg, ellers kan du ende i en uendelig løkke.

Den endelige kode kunne se sådan ud:

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

Det er klart, at ovenstående kode er suboptimal. Det kan være en god ide at skelne mellem fejl, der finder sted på forbindelsestidspunktet og fejl ved udførelsestidspunktet. Du kan også opdage, at der efter nogle fejl er lidt håb om, at endnu et forsøg vil virke (f.eks. forkerte legitimationsoplysninger eller SQL-syntaksfejl).

Du stillede mange spørgsmål, men jeg vil forsøge at besvare dem alle:

Ja, se ovenfor:SQLException 's er dem, med mere information leveret af getErrorCode() eller getSQLState() .

En SQLException kunne kastes af stort set alle metoder af alle klasser fra java.sql pakke.

Ja, se ovenfor.

Du må naturligvis ikke genskabe en PreparedStatement mellem to forespørgsler. Du skal blot indstille nye værdier til dine parametre, før du kalder executeQuery() en gang til. Selvfølgelig, hvis du har brug for at udføre en anden forespørgsel, så en ny PreparedStatement er påkrævet.

Et (nyt) ResultSet objekt returneres af Statement.executeQuery() , som repræsenterer resultatet af forespørgslen. Sådan et objekt skaber du aldrig selv. Ideelt set vil du kalde ResultSet.close() så hurtigt som muligt for at frigive hukommelsen.

Jeg råder dig kraftigt til at følge andet kapitel af denne vejledning ("Behandler SQL-sætninger").




  1. Indsæt ved hjælp af PreparedStatement. Hvordan øger jeg id'et automatisk?

  2. Returner standardresultat for IN-værdi uanset

  3. Hvordan overfører jeg min MySQL-database til en anden computer?

  4. Doktrin 2 DQL MySQL svarende til ROUND()?