一、前言
通过以下系列章节:
docker-compose 实现Seata Server高可用部署 | Spring Cloud 51
Seata AT 模式理论学习、事务隔离及部分源码解析 | Spring Cloud 52
Spring Boot集成Seata利用AT模式分布式事务示例 | Spring Cloud 53
我们对Seata
及其AT
事务模式的理论、使用有了深入的了解,今天继续对Seata
的XA
事务模式进行理论学习。
理论部分来自
Seata
官网:http://seata.io/zh-cn/docs/dev/mode/xa-mode.html
二、前提
- 支持
XA
事务的数据库。 Java
应用,通过JDBC
访问数据库。
三、整体机制
在 Seata
定义的分布式事务框架内,利用事务资源(数据库、消息服务等)对 XA
协议的支持,以 XA
协议的机制来管理分支事务的一种 事务模式。
-
执行阶段:
-
- 可回滚:业务
SQL
操作放在XA
分支中进行,由资源对XA
协议的支持来保证 可回滚 - 持久化:
XA
分支完成后,执行XA prepare
,同样,由资源对XA
协议的支持来保证 持久化(即,之后任何意外都不会造成无法回滚的情况)
- 可回滚:业务
-
完成阶段:
-
- 分支提交:执行
XA
分支的commit
- 分支回滚:执行
XA
分支的rollback
- 分支提交:执行
目前
Seata
的XA
模式分支注册的时机需要在XA
start
之前,详见 4.2章节 分支注册
四、工作机制
4.1 数据源代理
XA
模式需要 XAConnection
。
获取 XAConnection
两种方式:
- 方式一:要求开发者配置
XADataSource
- 方式二:根据开发者的普通
DataSource
来创建
第一种方式,给开发者增加了认知负担,需要为 XA
模式专门去学习和使用 XA
数据源,与 透明化 XA
编程模型的设计目标相违背。
第二种方式,对开发者比较友好,和 AT
模式使用一样,开发者完全不必关心 XA
层面的任何问题,保持本地编程模型即可。
我们优先设计实现第二种方式:数据源代理根据普通数据源中获取的普通 JDBC
连接创建出相应的 XAConnection
。
类比 AT
模式的数据源代理机制,如下:
但是,第二种方法有局限:无法保证兼容的正确性。
实际上,这种方法是在做数据库驱动程序要做的事情。不同的厂商、不同版本的数据库驱动实现机制是厂商私有的,我们只能保证在充分测试过的驱动程序上是正确的,开发者使用的驱动程序版本差异很可能造成机制的失效。
这点在
Oracle
上体现非常明显。
综合考虑,XA
模式的数据源代理设计需要同时支持第一种方式:基于 XA
数据源进行代理。
类比 AT
模式的数据源代理机制,如下:
4.2 分支注册
XA
start
需要 Xid
参数。
这个 Xid
需要和 Seata
全局事务的 XID
和 BranchId
关联起来,以便由 TC
驱动 XA
分支的提交或回滚。
目前 Seata
的 BranchId
是在分支注册过程,由 TC
统一生成的,所以 XA
模式分支注册的时机需要在 XA
start
之前。
将来一个可能的优化方向:
把分支注册尽量延后。类似AT
模式在本地事务提交之前才注册分支,避免分支执行失败情况下,没有意义的分支注册。
这个优化方向需要BranchId
生成机制的变化来配合。BranchId
不通过分支注册过程生成,而是生成后再带着BranchId
去注册分支。
五、XA 模式的使用
从编程模型上,XA
模式与 AT
模式保持完全一致。
通过以下配置实现 AT
模式向 XA
模式的切换:
seata:
enabled: true
enable-auto-data-source-proxy: true
data-source-proxy-mode: XA
AT
模式完整示例请见上期章节:Spring Boot集成Seata利用AT模式分布式事务示例 | Spring Cloud 53