How to properly handle InnoDB deadlocks in Java/JDBC?

可紊 提交于 2019-12-02 22:26:24

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").

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!