在新事务中更新要回滚事务的相同记录遇到了僵局

我的代码使用带有以下代码的Spring,Hibernate和DB2:

@Transactional
doSth(){
   Object obj = dao.getObject();
   try{
      classA.methodA(obj);
   }catch(Exception ex){
      classB.methodB(obj);
   }
}
ClassA:
methodA(Object obj){
   obj.setStatus("successful");
   throw new RuntimeException();
}
ClassB:
@Transational(propagation=REQUIRES_NEW)
methodB(Object obj){...
   obj.setStatus("failed");
}

methodA does not have @Transactional annotation and will use doSth's transaction

Both methodA and methodB are updating same record obj of a table.

With the given code, when exception is thrown in methodA after obj.setStatus("successful"), methodB will be stuck and wait forever.

I suppose, this is because when methodB is trying to update obj, the transaction used by methodA is not yet rolled back and it holds some db lock against obj.

So methodB is waiting for the lock from methodA, while methodA needs methodB to finish to rollback and release the lock, resulting in deadlock.

如我所测试,要解决此问题,有两种方法:

  1. Let the exception be thrown before obj.setStatus("successful"), so that obj is not yet updated by methodA

  2. Make methodA use @Transational(propagation=REQUIRES_NEW), so that its transaction is already rolled back by the time methodB is triggered

有人可以验证我的理解是否正确吗?这意味着如果两个事务的事务边界彼此重叠,则永远不要尝试更新同一记录。

评论