Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deadlock even with LockModeType.PESSIMISTIC_WRITE

When I trigger 10 requests in 1 second, org.springframework.dao.CannotAcquireLockException occurs.

Even though I marked my main method (calling repository methods inside) with @Transactional(isolation = Isolation.SERIALIZABLE) and my findBy method in repository has @Lock(LockModeType.PESSIMISTIC_WRITE) annotation.

On one environment everything works fine, but on the other environment error occurs. Any ideas why error occurs? Code is the same on both environments.

Stacktrace 1:

{"timestamp":"2017-08-21T12:18:16.16+0000","status":500,"error":"Internal Server Error","exception":"org.springframework.orm.jpa.JpaSystemException","message": "com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction; nested exception is javax.persistence.PersistenceException: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction","path":"/cars/toyota"}

Stacktrace 2:

{"timestamp":"2017-08-21T12:11:57.57+0000","status":500,"error":"Internal Server Error","exception":"org.springframework.dao.CannotAcquireLockException","message":"could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.LockAcquisitionException: could not execute statement","path":"/cars/toyota"}

like image 458
alxbxbx Avatar asked Oct 20 '25 06:10

alxbxbx


1 Answers

The error is thrown when you try to lock a row but the row is already locked by another transaction. So the timeout happens.

Adding the @Transactional(isolation = Isolation.SERIALIZABLE) makes it even worse because serializable level means one transaction locks entire table (modern oracle could somehow control this but for MySQl it's in fact a queue of transactions waiting to lock the same table). So 10th transaction waits for all previous 9 transactions and fails.

Actually I don't see why you need locks on findBy method. Logically the method should not modify the table so no need to lock at all.

I would suggest to change the logic to make one single call faster or even introduce optimistic locks (versions based) if you have concurrent modifications. Hibernate allows this by adding @Version.

like image 63
StanislavL Avatar answered Oct 21 '25 19:10

StanislavL



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!