当事务更新数千个实体时,如何避免StaleObjectStateException?

时间:2012-07-04 15:12:36

标签: java spring hibernate jpa transactions

我们正在将Hibernate 3.6.0.Final与JPA 2和Spring 3.0.5一起用于在tomcat 7和MySQL 5.5上运行的大型企业应用程序。应用程序中的大多数事务只能运行不到一秒钟并更新5-10个实体,但在某些用例中,我们需要在单个事务中更新10-20K以上的实体,这需要几分钟,因此超过70%的时间此类事务因StaleObjectStateException而失败,因为其中一些实体已被其他某些事务更新。

我们通常在所有表中维护版本列,并且在StaleObjectStateException的情况下我们通常会重试但是因为这些longs事务总是非常长,所以如果我们继续重试那么我也不能确定我们能够逃脱StaleObjectStateException

许多活动也会在繁忙的时间不断更新这些实体,因此我们不能采用悲观的方法,因为它可能会停止系统中的许多活动。

请建议如何解决这么长的交易问题,因为我们无法产生数以千计的独立和小额交易,因为我们无法承受一些失败的情况下的混乱数据。一些成功的交易。

1 个答案:

答案 0 :(得分:1)

在一个交易中修改20,000个实体真的很多,比平常更多。

我不能给你一个通用的解决方案,但这里有一些想法如何解决问题。

1)使用LockMode.UPGRADE(参见pessimistic locking)。在那里,您显式生成“SELECT FOR UPDATE”,它会阻止其他用户在锁定时修改行。 这应该可以避免您的问题,但是如果您有太多大型事务,它可能会产生死锁(取决于您的编程)或超时。

2)更改数据模型以避免这些大型事务。为什么要更新10,000行?也许可以将这些在这么多行中更新的信息放入一个新表中并让它只被引用,因此你只需要更新新表中的几行。

3)使用StatelessSession而不是Session。在这种情况下,您不会在异常后被迫回滚,而是可以纠正问题并继续(在您的情况下重新加载同时修改的实体并对重新加载的实体上的大事务进行修改)。这可能使您有可能在行到行的基础上处理关键事件(同时修改的行),而不是完整的大事务。