Search code examples
javaplayframeworkdeadlock

PlayFramework: catch a deadlock and reissue transaction


I am running a Play! application and am debugging a deadlock.

The error messages I see logged from Play! are:
Deadlock found when trying to get lock; try restarting transaction
Could not synchronize database state with session
org.hibernate.exception.LockAcquisitionException: Could not execute JDBC batch update

From the Play! Documentation

Play will automatically manage transactions for you. It will start a transaction for each HTTP request and commit it when the HTTP response is sent. If your code throws an exception, the transaction will automatically rollback.

From the MySQL Documentation

you must write your applications so that they are always prepared to re-issue a transaction if it gets rolled back because of a deadlock.

My question:
How and where in my Play! application can I catch these rolled back transactions, and handle them (choose to reissue them, ignore them, etc...)?

Updated
While I ended up taking the advice in the accepted answer, and looking for the cause of the deadlock (did you know MySQL foreign key constraints increase the chance of deadlocking? Now I do!), here is some code that was working for me to catch and reissue a failed save.

boolean success = false;
int tries = 0;
while (!success && tries++ < 3) {
    try {
        updated.save();
        success = true;
    } catch (javax.persistence.PersistenceException e) {
        pause(250);  
    }
}

Solution

  • In most cases of a deadlock you can only do a rollback and try a restart. How ever in a Webapp this should be a really unusual case. What you can do in Play is

    • catch the exception
    • handle the Transaction in your code

    With JPA.em() you will get the EntityManager. You can look into JPAPlugin to see how play handle the transaction. How ever first of all I would evaluate why there is a deadlock and if this is really a realistic situation which can the server handle intelligent.