休眠超时锁定等待超时;

编程入门 行业动态 更新时间:2024-10-24 01:59:27
本文介绍了休眠超时锁定等待超时;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

编辑:我搬了em1.getTransaction()。提交是正确的之后em1.flush();

会话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(); //失败 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错误:1205,SQLState:41000 2009-12-23 21:48:37,649错误JDBCExceptionReporter:101 - 锁超时超时;尝试重新启动事务错误AbstractFlushingEventListener:324 - 无法使数据库状态与会话同步org.hibernate.exception.GenericJDBCException:无法执行JDBC批量更新在org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126)在org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114)在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。 at org.hibernate.persister.entity.AbstractEntityPersister.processUpdateGeneratedProperties(AbstractEntityPersister.java:3691) at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:147)$ b $ org.hibernate.engine。 ActionQueue.execute(ActionQueue.java:279)在org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)在org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java: 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)导致:java .sql.BatchUpdateException:超出锁定等待超时;尝试重新启动事务在com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1213)在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

解决方案

好吧,您正试图陷入僵局,而您成功: - )

  • Transaction1启动,更新(和锁定)与您的实体一起。
  • Transaction2试图做同样的事情,但不能,因为行仍然被锁定。因此,它会等待(等待,等待),直到超时。
  • $ b

    真实生活和第二个实体管理器加上适当的更新/交易在不同的线程。这样您就可以:

  • Transaction1启动,更新(并且锁定)与您的实体一致的行。
  • Transaction2试图做同样的事情,但不能,因为行仍然被锁定。所以它等待(等待,等待)......
  • 同时Transaction1被提交并且锁定被释放
  • Transaction2现在可以继续
  • >

    请注意,在这一点(上面#4),您将覆盖Transaction1所做的更改。 Hibernate可以使用乐观锁定以及悲观锁定,以防止这种情况发生。

    更新(基于评论):

    如果实体版本化,Transaction2(上面的#4)将失败。但是,您发布的代码没有达到该点,因为Transaction2无法获得上述的锁定。如果您想专门测试乐观版本控制是否正常工作,您可以执行以下操作:

  • 获取em1,启动事务,获取您的实体, 提交事务,关闭 em1。
  • 获取em2,启动事务,获取实体,更新实体,提交事务,关闭em2 。
  • 获取em3,启动事务,尝试更新您在步骤1中加载的实体 - 测试应该在此处失败。
  • I am using Hibernate, trying to simulate 2 concurrent update to the same row in database.

    Edit: I moved em1.getTransaction()mit to be right after em1.flush(); I am not getting any StaleObjectException, the two transactions committed successfully.

    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()mit(); em2.getTransaction()mit(); System.out.println("balance2 is "+c2.getBalance());

    I getting the following exception on em2.flush(). Why?

    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

    解决方案

    Well, you're trying to get into a deadlock and you're succeeding :-)

  • Transaction1 starts, updates (and locks) row with your entity.
  • Transaction2 tries to do the same but can't because the row is still locked. So it waits (and waits, and waits) until timeout is exceeded
  • Real life simulation would have 1st and 2nd entity manager plus appropriate updates / transactions in separate threads. That way you'd have:

  • Transaction1 starts, updates (and locks) row with your entity.
  • Transaction2 tries to do the same but can't because the row is still locked. So it waits (and waits, and waits) ...
  • Meanwhile Transaction1 is committed and lock is released
  • Transaction2 can now proceed
  • Note that at that point (#4 above) you'd be overwriting changes made by Transaction1. Hibernate can use optimistic locking as well as pessimistic locking to prevent that from happening.

    Update (based on comment):

    If the entity is versioned, Transaction2 (#4 above) will fail. However, your code as posted does not get to that point because Transaction2 can't obtain the lock as explained above. If you want to specifically test that optimistic version control is working you can do the following:

  • Obtain em1, start transaction, get your entity, commit transaction, close em1.
  • Obtain em2, start transaction, get your entity, update your entity, commit transaction, close em2.
  • Obtain em3, start transaction, attempt to update entity you've loaded in step 1 - test should fail here.
  • 更多推荐

    休眠超时锁定等待超时;

    本文发布于:2023-11-05 12:35:37,感谢您对本站的认可!
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!