How to properly handle InnoDB deadlocks in Java/JDBC?

前端 未结 1 728
小鲜肉
小鲜肉 2021-02-03 11:21

I am working on a theory basis here, I want to make sure all my bases are covered.

I have read quite a bit into InnoDB with Java and how deadlocks can occur no matter wh

1条回答
  •  伪装坚强ぢ
    2021-02-03 11:34

    Your code is essentially correct. The exception raised when a dead lock occurs is a SQLException. The exception's getSQLState() method provides returns an error code that provides additional information about the actual error.

    You should also wait a short amount of time between attemps, so as not to load your server too much.

    As you cleverly guessed, set a maximum number of attempts, or you might end-up in an infinite loop.

    The final code could look like this:

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

    Obviously the above code is sub optimal. You may want to differentiate errors taking place at connection time and errors at execution time. You could also detect that after some errors, there is little hope that another attempt will work (eg. wrong credentials or SQL syntax error).

    You asked a lot of questions, but I will try to answer them all:

    Are there specific exceptions to listen out for?

    Yes, see above: SQLException's are the ones, with more information provided by getErrorCode() or getSQLState().

    Is the exception only thrown after I call connection.commit()?

    A SQLException could be thrown by virtually all methods of all classes from the java.sql package.

    Should things be running in a loop with a limit to how many times the loop runs?

    Yes, see above.

    Do I [need to] re-instantiate PreparedStatement objects?

    Obviously you must not re-create a PreparedStatement between two queries. You just need to set new values to your parameters before calling executeQuery() again. Of course if you need to execute another query, then a new PreparedStatement is required.

    Same goes for ResultSet objects too

    A (new) ResultSet object is returned by Statement.executeQuery(), which represents the result of the query. You never create such an object yourself. Ideally you will call ResultSet.close() as soon as possible to release memory.

    I strongly advise you to follow the second chapter of this tutorial ("Processing SQL Statements").

    0 讨论(0)
提交回复
热议问题