对于在Tomcat7和MySQL 5.5上运行的大型企业应用程序,我们使用Hibernate 3.6.0 scale与JPA2和Spring3.0.5。应用程序中的大多数事务存在时间不到一秒,并更新5-10个实体,但在某些用例中,我们需要在单个事务中更新超过10-20,000个实体,这需要几分钟的时间,因此超过70%的此类事务使用StaleObjectStateException失败,因为这些实体中的一些被其他事务更新。
我们通常在所有的表中维护version列,在StaleObjectStateException的情况下,我们通常会重试,但由于这些长事务无论如何都很长,所以如果我们继续重试,那么我也不太确定我们是否能够避开StaleObjectStateException。
此外,许多活动在繁忙时间不断更新这些实体,因此我们不能采用悲观的方法,因为这可能会导致系统中的许多活动停止。
请建议如何解决如此长的事务问题,因为我们不能产生数千个独立的小事务,因为我们不能在一些失败和成功的事务的情况下处理混乱的数据。
发布于 2012-07-05 20:18:46
在一个事务中修改20,000个实体真的很多,比正常情况下要多得多。
我不能给你一个通用的解决方案,但这里有一些如何解决这个问题的想法。
1)使用LockMode.UPGRADE (参见pessimistic locking)。在这里,您显式地生成"SELECT FOR UPDATE",它阻止其他用户在行被锁定时对其进行修改。这应该可以避免您的问题,但是如果您有太多的大型事务,可能会产生死锁(取决于您的编程)或超时。
2)更改您的数据模型,以避免这些大型事务。为什么要更新10,000行?也许可以将这个在许多行中更新的信息放到一个新表中,并让它只被引用,这样您就只需要在新表中更新几行。
3)使用StatelessSession代替Session。在这种情况下,您不会在异常后强制回滚,而是可以纠正问题并继续(在您的情况下,重新加载同时修改的实体,并在重新加载的实体上对大型事务进行修改)。这可能使您可以逐行处理关键事件(同时修改行),而不是处理完整的大型事务。
https://stackoverflow.com/questions/11331718
复制相似问题