您需要更清楚地定义您的要求。“嵌套事务”是模棱两可的。这可能意味着简单地暂停一个事务以运行另一个事务,然后恢复第一个事务:
transactionManager.begin();
// now in tx A
transaction txA = transactionManager.suspend();
// no tx active here
transactionManager.begin();
// now in tx B
transactionManager.commit(); // tx B ends
// no tx active here
transactionManager.resume(txA);
// now in tx A again
transactionManager.commit(); // tx A ends
这在您需要执行一些操作时很常见,例如审计日志更新,这在逻辑上与外部事务是分开的。任何事务管理器都会这样做,尽管很少编写如此直接驱动 TM 的代码。请改用 EJB 容器。
然后你会遇到这样的情况,你只需要伪嵌套来更容易地构建逻辑:
// no tx active at start
transactionManager.begin();
// tx A now active, nesting count = 1
transactionManager.begin();
// tx A still active, nesting count = 2
transactionManager.commit();
// nullop, tx A still active, nesting count = 1
transactionManager.commit();
// tx A really committed, no tx active, count = 0.
乍一看,这看起来很有吸引力,但是当发生嵌套回滚时,它会带来更多的麻烦。未得到广泛支持,尽管某些数据库允许这样做以使存储过程的处理更容易。
最后,您拥有真正的嵌套事务,其中子事务从其父事务继承锁,并在完成时将自己的锁传递给该父事务
transactionManager.begin();
// now in tx A1
transactionManager.begin();
// now in tx A1.1
// can see uncommitted changes made by A1
transactionManager.commit(); // validate ability to make A1.1 changes permanent, but do not actually do so yet
// now in tx A1, still holding locks from A1.1 also
transactionManager.commit(); // commit A1 and A1.1 changes atomically.
这主要用于故障隔离 - 可以回滚子事务并执行其他操作,而不会对外部事务造成任何影响。这是一个非常强大的事务模型。实现起来也很棘手——目前只有 JBossTS 支持它。并不是说它在大多数 Java EE 用例中对您有多大好处,因为没有资源管理器(即数据库或消息队列)支持它。
至于 MVCC,这与事务管理器完全无关。您的业务数据保存在资源管理器中,通常是关系数据库。RM 用于提供 tx 隔离和并发控制的模型与驱动事务的方式是正交的。Oracle 和 postgres 偏爱 MVCC,而其他一些 dbs 偏爱表、页或行级锁定。事务管理器不知道也不关心。