入口: 根据前一篇文章,得知入口是 TransactionInterceptor
XA 规范说明:
对多个数据源操作
d1:
1) d1XAResource.start: xa事务准备
2) d1.prepareStatement sql拼接以及sql执行,不commit
3) d1XAResource.end xa事务准备完成
d2:
1) d2XAResource.start: xa事务准备
2) d2.prepareStatement sql拼接以及sql执行,不commit
3) d2XAResource.end xa事务准备完成
4) d1XAResource.prepare
5) d2XAResource.prepare
6) d1XAResource.commit commit
7) d2XAResource.commit commit
Mysql对XA事务支持:
XA {START|BEGIN} xid [JOIN|RESUME] //开启XA事务,如果使用的是XA START而不是XA BEGIN,那么不支持[JOIN|RESUME],xid是一个唯一值,表示事务分支标识符
XA END xid [SUSPEND [FOR MIGRATE]] //结束一个XA事务,不支持[SUSPEND [FOR MIGRATE]]
XA PREPARE xid 准备提交
XA COMMIT xid [ONE PHASE] //提交,如果使用了ONE PHASE,则表示使用一阶段提交。两阶段提交协议中,如果只有一个RM参与,那么可以优化为一阶段提交
XA ROLLBACK xid //回滚
XA RECOVER [CONVERT XID] //列出所有处于PREPARE阶段的XA事务
1.1 TransactionInterceptor.invokeWithinTransaction
1.1.1 invokeWithinTransaction.createTransactionIfNecessary
为每一个数据库操作创建一个子事务(基于动态代理,所以方法必须是public)
1.1.2 invokeWithinTransaction#invocation.proceedWithInvocation()
a、具体的业务代码执行,sql会执行,开启读未提交,在此阶段执行完成之后,可以看到数据
b、会对每个子事务进行 XAResource.start操作,会到mysql中执行start指令,标志分布式事务开启
1.1.3 invokeWithinTransaction.commitTransactionAfterReturning
1.1.3.1 AbstractPlatformTransactionManager.commit
1.1.3.1.1 AbstractPlatformTransactionManager.triggerBeforeCompletion
对每个子事务进行 XAResource.end操作,会到mysql中执行end指令,标志分布式事务结束
1.1.3.1.2 JTATransactionManager.doCommit
1.1.3.1.2.1 CoordinatorImp
最重要的逻辑判断,实现了
XAResource.prepare,即sql执行,如果prepare阶段报错了,则进行rollback,如果prepare阶段成功看了,则commit
会到mysql中执行prepare指令,通知mysql我要提交事务了,给我准备好资源
会到mysql中执行commit指令, 提交事务
synchronized ( fsm_ ) {
if ( commit ) {
if ( participants_.size () <= 1 ) {
commit ( true );
} else {
int prepareResult = prepare ();
if ( prepareResult != Participant.READ_ONLY )
commit ( false );
}
} else {
rollback ();
}
}