我们正在运行最新版本的 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/