繁体   English   中英

如何使用Java持久性重试锁定等待超时?

[英]How to retry a lock wait timeout using java persistence?

我需要对使用Java持久性时重试“可重试”异常(例如类似锁等待超时之类)的正确方法进行一些说明。 例如,使用伪代码,例如:

EntityTransaction tx = em.getTransaction();
tx.begin();
for (a bunch of objects) {
  em.persist(object);
}
tx.commit();

如果数据库中有锁,有时会在em.persist调用中引发异常。 我可以将其包装在try / catch中然后重试吗(很明显,有一些计数)? 还是我必须包装整个tx.begin / commit并重

谢谢

假设没有锁定超时作为解决数据库死锁的方法,那么一个更简单的解决方案是对请求使用更长的超时。 将超时设置为N * (C + 1)秒,而不是使用N秒的超时并重试最多C次。

(如果您将锁定超时用作死锁的一种解决方法,那么您会遇到更大的问题。您最好尝试解决死锁的根本原因,因为即使使用C重试,您的交易也有可能获胜不能通过。)

只要EntityManager抛出的异常不会将事务标记为仅回滚(LockTimeoutException是此类示例之一,而PessimisticLockException并非如此),则可以继续处理当前事务中的事务。

如果TX仅被标记为回滚,则您必须对TX进行保释,然后重试TX内发生错误之前的任何尝试,然后继续操作。

如果要通过JPA循环进行工作,那么您很有可能是DELETE或UPDATE jpql查询的候选人。

如果您按照规范进行编程,则实际上应该处置整个EntityManager并重新开始。 没有任何例外可以保证在EM级别“可重试”。 如果persist()方法产生异常,则整个持久性会话将被视为不一致/不确定。

有时它将起作用。 我知道在休眠状态下,您通常可以在乐观锁定异常之后尝试获得收益。 但是总的来说,如果您试图捕获并从entitymanager异常中恢复并保持相同的entitymanager,则您将依赖于供应商特定的行为,这些行为可能定义不清。

更多信息在这里。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM