Getting "Deadlock found when trying to get lock; try restarting transaction"

If you are using JPA/Hibernate then simple just follow below steps to avoid dead lock. Once you have acquired the lock, don't made any call on db with same id anywhere in the transaction (I mean to say you should not get entity again on sameid), on locking object you modify and save no issues.

service level:-

employee=empDao.getForUpdate(id);

Dao level:-

public employee getForUpdate(String id)
return mySqlRepository.getForUpdate(id)

Repository(interface):-

@Lock(LockModeType.PESSIMITSIC_WRITE)
@Query("select e from employee e where id=?1")
public employee getForUpdate(String id)

MySQL's InnoDB engine sports row-level locking, which can lead to deadlocks even when your code is inserting or updating a single row (specially if there are several indexes on the table being updated). Your best bet is to design the code around this in order to retry a transaction if it fails due to a deadlock. Some useful info about MySQL deadlock diagnose and possible workarounds is available here.

An interesting implementation of deadlock retry via AOP in Spring is available here. This way you just need to add the annotation to the method you want to retry in case of deadlock.


Emir's answer is great and it describes the problem that you are getting. However I suggest you to try spring-retry.

It's a brilliant framework that implements the retry pattern via annotation(s).

Example:

 @Retryable(maxAttempts = 4, backoff = @Backoff(delay = 500))
 public void doSomethingWithMysql() {
   consumerTransactionTemplate.execute(
             new TransactionCallbackWithoutResult(){
                @Override
                protected void doInTransactionWithoutResult(                 
                      TransactionStatus status)
                {
                    process();
                }

            });
 } 

In case of exception, it will retry (call) up to 4 times the method doSomethingWithMysql() with a backoff policy of 500ms