sql >> Databasteknik >  >> RDS >> Mysql

Hur hanterar man InnoDB dödlägen korrekt i Java/JDBC?

Din kod är i princip korrekt. Undantaget som uppstår när ett dödlås inträffar är en SQLException . Undantagets getSQLState() metod tillhandahåller returnerar en felkod som ger ytterligare information om det faktiska felet.

Du bör också vänta en kort tid mellan försöken för att inte ladda din server för mycket.

Som du skickligt gissade, ställ in ett maximalt antal försök, annars kan du hamna i en oändlig loop.

Den slutliga koden kan se ut så här:

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

Uppenbarligen är ovanstående kod suboptimal. Du kanske vill skilja på fel som uppstår vid anslutningstidpunkten och fel vid körningstidpunkten. Du kan också upptäcka att efter vissa fel finns det lite hopp om att ett nytt försök kommer att fungera (t.ex. felaktiga referenser eller SQL-syntaxfel).

Du ställde många frågor, men jag ska försöka besvara dem alla:

Ja, se ovan:SQLException s är de, med mer information tillhandahållen av getErrorCode() eller getSQLState() .

En SQLException kan kastas av praktiskt taget alla metoder av alla klasser från java.sql paket.

Ja, se ovan.

Självklart får du inte återskapa en PreparedStatement mellan två frågor. Du behöver bara ställa in nya värden för dina parametrar innan du anropar executeQuery() på nytt. Naturligtvis om du behöver köra en annan fråga, sedan en ny PreparedStatement krävs.

En (ny) ResultSet objektet returneras av Statement.executeQuery() , som representerar resultatet av frågan. Du skapar aldrig ett sådant objekt själv. Helst anropar du ResultSet.close() så snart som möjligt för att frigöra minnet.

Jag rekommenderar starkt att du följer det andra kapitlet i denna handledning ("Bearbetar SQL-satser").




  1. Kö i OneWay WCF-meddelanden med Windows Service och SQL Server

  2. SQL join-resultat till ett objekt i codeigniter

  3. Finns det en optimal metod för att beställa ett MySQL-kompositindex?

  4. SQL:Hur håller man ordning på raderna med DISTINCT?