java - 使用乐观锁定时的 Hibernate/MySQL LockTimeoutException

标签 java mysql hibernate jpa

我们正在运行最新版本的 Hibernate 4 和 MySQL。我们所有的 Hibernate 实体都有一个用 @Version 注释的版本字段,因为我们全面使用乐观锁定。我们在应用程序的任何地方都没有使用悲观锁定。我的理解是 LockTimeoutExceptions 在使用悲观锁定时可能会发生,但是,即使我们不使用这种锁定策略,我们也会经常遇到这些问题。

在这个特定场景中,我们有一个线程池大小为 1 的执行程序服务。当用户执行某些操作时,我们会为其他用户创建通知。我们将此通知创建委托(delegate)给执行程序服务。这些通知可能需要一些时间来创建,所以我们这样做是为了让用户不必坐下来等待通知创建完成。我们使用单一大小的线程池,这样我们就不会多次处理通知等。我们想要的是让这些操作排队并按顺序运行。每个线程启动一个事务,创建所有必要的通知并提交所述事务并关闭实体管理器。

我们得到的异常的堆栈跟踪如下。任何想法为什么我们会在上述场景中获得锁定?我不明白。

Lock wait timeout exceeded; try restarting transaction
    2015-10-08 01:27:52,195 ERROR [NotificationPublishingRunnable] : could not execute statement
    javax.persistence.LockTimeoutException: could not execute statement
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.wrapLockException(AbstractEntityManagerImpl.java:1812)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1715)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1206)
        at za.co.bsg.ems.server.DB.merge(171bcc9:315)
        at za.co.bsg.ems.server.repositories.AbstractRepository.merge(171bcc9 ---------------:158)
        at za.co.bsg.ems.server.services.notification.EmployeeNotificationCRUDServiceSupport.createEmployeeNotification(171bcc9 remotes/origin/11_9 ---------------:97)
        at za.co.bsg.ems.server.services.notification.EmployeeNotificationCRUDServiceSupport.createEmployeeNotifications(171bcc9 remotes/origin/11_9 ---------------:75)
        at za.co.bsg.ems.server.services.notification.EmployeeNotificationCreatorSupport.createEmployeeNotifications(171bcc9 remotes/origin/11_9 -----------:80)
        at za.co.bsg.ems.server.notification.handler.NotificationHandlerManagerSupport.createNotificationsFromRequest(171bcc9 remotes/origin/11_9 ----------:233)
        at za.co.bsg.ems.server.runnable.notification.NotificationPublishingRunnable.run(171bcc9 remotes/origin/11_9 -------:64)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
    Caused by: org.hibernate.exception.LockTimeoutException: could not execute statement
        at org.hibernate.dialect.MySQLDialect$1.convert(MySQLDialect.java:447)
        at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
        at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211)
        at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:96)
        at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:58)
        at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3032)
        at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3558)
        at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:98)
        at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:492)
        at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:197)
        at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:181)
        at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:216)
        at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:324)
        at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
        at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
        at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
        at org.hibernate.jpa.event.internal.core.JpaMergeEventListener.saveWithGeneratedId(JpaMergeEventListener.java:73)
        at org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:271)
        at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:251)
        at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:189)
        at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:85)
        at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:876)
        at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:858)
        at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:863)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1196)
        ... 10 more
    Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:996)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3887)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3823)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2530)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1907)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2141)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2077)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2062)
        at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
        at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
        at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208

最佳答案

我遇到了同样的问题,是因为我开始了一个事务没有提交,然后又开始了另一个事务。

提交第一笔交易解决了这个问题。

关于java - 使用乐观锁定时的 Hibernate/MySQL LockTimeoutException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33012856/

相关文章:

java - Spring Framework Autowiring 空指针异常

java - 多种颜色/笔画手势和在同一个 GestureOverlayView 中持续绘图

php - 函数返回 bool 值而不是字符串

java - 为什么 session.createCriteria(classtype).list() 返回的对象比列表中的对象多?

java - 如何使用 Spring 和 Hibernate 调用具有两个参数的存储过程

java - rxjava 当超时时跳过项目并继续下一个项目

mysql - 从具有多个自定义列的现有表创建新表

mysql - 大数据文件、操作和搜索

database - 数据库迁移 - Hibernate/JPA - hbm2ddl - diff 工具

java - 如何将此 Android 电子邮件发送代码投入使用?