2015-10-08 3 views
1

Мы используем последнюю версию Hibernate 4 и MySQL. Все наши объекты Hibernate имеют поле версии, аннотированное @Version, поскольку мы используем Оптимистическое блокирование по всей доске. Нигде в приложении мы не используем Pessimistic Locking. Мое понимание заключалось в том, что LockTimeoutExceptions может возникать при использовании пессимистического блокирования, однако мы получаем их все так часто, хотя мы не используем эту стратегию блокировки.Hibernate/MySQL LockTimeoutException при использовании оптимистической блокировки

В этом конкретном случае у нас есть служба-исполнитель с пулом потоков размером 1. Когда пользователи выполняют определенные действия, мы создаем уведомления для других пользователей. Мы делегируем это уведомление для службы исполнителя. Эти уведомления могут занять некоторое время для создания, поэтому мы делаем это таким образом, чтобы пользователю не приходилось сидеть и ждать завершения создания уведомлений. Мы используем однопоточный пул потоков, так что мы не обрабатываем несколько обработок уведомлений и т. Д. Мы хотели, чтобы эти операции имели скорее очередь и выполнялись последовательно. Каждый поток запускает одну транзакцию, создает все необходимые уведомления и совершает указанную транзакцию и закрывает диспетчер объектов.

Трассировка стека за исключением, которое мы получаем ниже. Любые идеи, почему мы должны получить блокировку в сценарии, таком как выше? Я этого не понимаю.

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 
+0

[@ brent777] Вы когда-нибудь находили решение этой проблемы? У нас такая же проблема. –

+0

@AndrewKew, к сожалению, нет. – brent777

ответ

0

Вы аннотируете все свои сущности с помощью @Version: Это означает, что вы хотите использовать оптимистичную блокировку. Оптимистическая блокировка управляется EntityManger, DAO или Repository.

Здесь вы используете подготовленное состояние для запроса своей базы данных. Таким образом, вы используете пессимистическую блокировку, которая по умолчанию является функцией некоторых баз данных. Именно по этой причине у вас есть исключение LockTimeoutException.

+0

Этот ответ не помогает вообще, он в основном повторяет то, что я уже сказал в моем вопросе. Кроме того, оптимизированная блокировка используется во всем приложении, она не возвращается к пессимистической блокировке из-за «базы данных по умолчанию», как вы предлагаете. Я знаю это, потому что мы также получаем OptimisticLockExceptions при других обстоятельствах для этого же объекта. – brent777

+1

Brent777 Я не знаю, понимаю ли я ваш вопрос. Вы говорите (в своем названии) у вас есть исключение LockTimeOutException при использовании Optimistic Locking. В моем ответе говорилось, что вы не используете оптимистичную блокировку, а пессимистичную блокировку, поскольку используете PreparedStatement. Если нет, то каков ваш вопрос? – Pracede

+0

Мой вопрос в том, как можно получить исключение LockTimeoutException в среде OptimisticLocking. Как я уже сказал в своем предыдущем комментарии, я не считаю, что пессимистическая блокировка используется только потому, что задействованы подготовленные заявления. Тогда почему я должен получить OptimisticLockExceptions для одного и того же объекта? Почему иногда это оптимистично, а иногда и пессимистично, когда все мои запросы записываются точно так же и выполняются через Entity Manager как именованные запросы? Какова ваша ссылка на подготовленные заявления с использованием пессимистической блокировки, даже если у меня есть конкретные поля Версии? – brent777

Смежные вопросы