伪代码:
Class A {
@Transactional(rollbackFor = Exception.class)
public String transactionA() {
Object savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
try {
// 省略可能报错的代码
TableA a = new TableA();
a.setId(1);
tableAMapper.insert(a);
}catch(Exception e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
}finally {
LogMapper.insert(new Log("time","method","request","response"));
}
}
}
Class B {
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void transactionB() {
Object savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
try {
// 省略可能报错的代码
TableA a = new TableA();
a.setId(1);
a.status(2);
tableAMapper.update(a);
}catch(Exception e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
}finally {
LogMapper.insert(new Log("time","method","request","response"));
}
}
}
TableA 表的 id 有主键约束,唯一索引。其他没有任何索引。
上面代码会产生 Lock wait timeout exceeded 的错误。
我通过检索资料,大概了解到问题原因,是事务 A 中tableAMapper.insert(a);
触发了(行、排他锁),事务 B 里一直拿不到锁,导致超时。
但是我还想事务 B 拥有自己的事务,并且进行手动回滚。(因为我想在哪怕报错的时候 也要进行一段日志记录的数据库插入操作)
不知道有没有解决办法。或者其他思路?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.