简体   繁体   中英

Spring JPA + MySQL Deadlock found on commit but the deadlock is not registered into the error_log of the database

I have a method annotated with @Transactional which obtain messages and perform some operations on the database to persist things correctly.

Now, some times this method throws a DeadLock with the following stacktrace:

Caused by: org.hibernate.TransactionException: Unable to commit against JDBC Connection
        at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.commit(AbstractLogicalConnectionImplementor.java:87)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:272)
        at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104)
        at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:532)
        ... 34 common frames omitted
Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:123)
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
        at com.mysql.cj.jdbc.ConnectionImpl.commit(ConnectionImpl.java:813)
        at com.zaxxer.hikari.pool.ProxyConnection.commit(ProxyConnection.java:361)
        at com.zaxxer.hikari.pool.HikariProxyConnection.commit(HikariProxyConnection.java)
        at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.commit(AbstractLogicalConnectionImplementor.java:81)
        ... 37 common frames omitted

The problem I am facing is that on the database side, MySQL is not registering any deadlock to happen in that moment.

I've enabled the innodb_print_all_deadlocks variable and I verified that it is working as expected by manually raising deadlocks which are immediately logged by the db.

I've also verified that when a real deadlock happens within the application (with real I mean that MySQL logs the deadlock on its side), the stacktrace is different and usually the deadlock is found by the database server way before the commit, for example when the application tries to ClientPreparedStatement.executeUpdateInternal .

It looks weird to me that the deadlock is raised on ConnectionImpl.commit . I've checked the ConnectionImpl code and I can't understand why a deadlock could be thrown there (at the line in the stacktrace, there's just return; )

Is it possible that JPA is somehow raising a deadlock on the app side?

Leaving this as it might help other people stuck with the same weird problem.

The reason for my problem was the fact that the application was using MariaDB driver instead of MySQL one. For some reasons, the MariaDB driver was throwing fake deadlock exceptions, so the MySQL server was correct in not logging any deadlock happening.

Switching the driver with the more correct one, all problems stopped.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM