будьте в спящем режиме Блокировка ожидает, тайм-аут превысил;

Я использую, в спящем режиме, пытаясь моделировать 2 параллельных обновления той же строки в базе данных.

Править: Я переместил em1.getTransaction () .commit для права после em1.flush (); я не получаю StaleObjectException, эти две транзакции, фиксировавшие успешно.

Session em1=Manager.sessionFactory.openSession();
Session em2=Manager.sessionFactory.openSession();

em1.getTransaction().begin();
em2.getTransaction().begin();

UserAccount c1 = (UserAccount)em1.get( UserAccount.class, "root" );
UserAccount c2 = (UserAccount)em2.get( UserAccount.class, "root" );

c1.setBalance( c1.getBalance() -1 );
em1.flush();
System.out.println("balance1 is "+c2.getBalance());
c2.setBalance( c2.getBalance() -1 );
em2.flush(); // fail

em1.getTransaction().commit();
em2.getTransaction().commit();

System.out.println("balance2 is "+c2.getBalance());

Я надевающий следующее исключение em2.flush(). Почему?

2009-12-23 21:48:37,648  WARN JDBCExceptionReporter:100 - SQL Error: 1205, SQLState: 41000
2009-12-23 21:48:37,649 ERROR JDBCExceptionReporter:101 - Lock wait timeout exceeded; try restarting transaction
2009-12-23 21:48:37,650 ERROR AbstractFlushingEventListener:324 - Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126)
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
    at org.hibernate.persister.entity.AbstractEntityPersister.processGeneratedProperties(AbstractEntityPersister.java:3702)
    at org.hibernate.persister.entity.AbstractEntityPersister.processUpdateGeneratedProperties(AbstractEntityPersister.java:3691)
    at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:147)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
    at com.ch.whoisserver.test.StressTest.main(StressTest.java:54)
Caused by: java.sql.BatchUpdateException: Lock wait timeout exceeded; try restarting transaction
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1213)
    at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:912)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
    ... 10 more
10
задан spaaarky21 3 January 2013 в 06:42
поделиться

1 ответ

Ну, вы пытаетесь зайти в тупик и получается :-)

  1. Transaction1 начинает, обновляет (и блокирует) строку с вашей сущностью.
  2. Transaction2 пытается сделать то же самое, но не может, потому что строка все еще заблокирована. Поэтому она ждет (и ждет, и ждет) истечения таймаута

Реальная жизнь симуляция будет иметь 1-й и 2-й менеджер сущностей плюс соответствующие обновления/транзакции в отдельных потоках. Таким образом, вы бы имели:

  1. Transaction1 начинает, обновляет (и блокирует) строку с вашей сущностью.
  2. Transaction2 пытается сделать то же самое, но не может, потому что строка все еще заблокирована. Поэтому она ждет (и ждет, и ждет) ...
  3. Тем временем транзакция 1 фиксируется и блокировка освобождается
  4. Сделка2 может теперь продолжить

Обратите внимание, что в этот момент (#4 выше) вы перезаписываете изменения, сделанные транзакцией 1. Спящий режим может использовать оптимистическую блокировку, а также пессимистическую блокировку, чтобы предотвратить это.

Обновление (на основе комментария):

Если сущность версионирована, транзакция 2 (#4 выше) будет неудачной. Однако, ваш код в виде пост-версии не дойдет до этой точки, потому что Transaction2 не может получить блокировку, как объяснялось выше. Если вы хотите специально проверить, что оптимистичный контроль версий работает, вы можете сделать следующее:

  1. Получить em1, начать транзакцию, получить вашу сущность, commit transaction, close em1.
  2. Получить em2, начать транзакцию, получить вашу сущность, обновить вашу сущность, зафиксировать транзакцию, закрыть em2.
  3. Получить em3, запустить транзакцию, попытаться обновить сущность, загруженную на шаге 1 - тест здесь не пройдет.
22
ответ дан 3 December 2019 в 17:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: