Java分布式事务
Sharding-JDBC的本地事务在网络、硬件故障下是无法保证分布式事务。
Sharding-JDBC目前还整合其他分布式事务模式来解决事务问题,来介绍一下两阶段事务XA是如何解决分布式事务

什么是XA规范

XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准。
XA 规范描述了全局的事务管理器与局部的资源管理器之间的接口。XA规范的目的是允许多个资源(如数据库,应用服务器,消息队列等)在同一事务中访问,这样可以使 ACID 属性跨越应用程序而保持有效。
XA 规范使用两阶段提交来保证所有资源同时提交或回滚任何特定的事务。
XA 事务的基础是两阶段提交协议。需要有一个事务协调者来保证所有的事务参与者都完成了准备工作(第一阶段)。如果协调者收到所有参与者都准备好的消息,就会通知所有的事务都可以提交了(第二阶段)。
MySQL 在这个 XA 事务中扮演的是参与者的角色,而不是协调者(事务管理器)。
MySQL中的XA事务分为外部XA和内部XA:

  1. 外部XA:可以参与外部的分布式事务,需要协调者参与协调
  2. 内部XA:用于同一实例下跨多引擎事务,由 Binlog 作为协调者,比如在一个存储引擎提交时,需要将提交信息写入二进制日志,这就是一个分布式内部 XA 事务,只不过二进制日志的参与者是 MySQL 本身。

基于XA规范分布式事务对业务是无侵入的,用户可以像使用本地事务一样使用基于XA规范的分布式事务。
但是基于XA规范的分布式事务属于强一致性事务,性能比较低,尤其在长事务的情况下,对资源的锁定时间较长,一般适用于短事务、低并发的场景

MySQL中XA事务

接下来就以为MySQL中XA来演示一下,如下;
一个注解搞定分布式事务 - 图1
上述命令什么意思呢?解析如下:

  1. **XA START "test_xid"**:开启一个XA事务,test_xid是全局事务xid,名称任意
  2. **update product_base set price=1000 where product_id=743948772064624640**:执行的SQL语句
  3. **XA END "test_xid"**:这个表示结束一个 XA 事务,此时事务的状态转为 IDLE。
  4. **XA PREPARE "test_xid"**:这个将事务置为 PREPARE 状态
  5. **XA COMMIT "test_xid"**:这个用来提交事务,提交之后,事务的状态就是 **COMMITED**
  6. **XA ROLLBACK "test_xid"**:这个用来回滚事务

    Sharding-JDBC中的XA事务

    Sharding-JDBC目前已经整合了XA事务的支持,支持的**Atomikos**NARAYANABITRONIX 事务的实现,默认的实现是Atomikos。下面将以**Atomikos**为例子介绍一下Sharding-JDBC如何实现XA事务
    SharingSphere是通过SPI的方式去定制分布式事务解决方案的,XA的默认实现是org.apache.shardingsphere.transaction.xa.XAShardingTransactionManager,有兴趣的可以看下其中源码
    后文介绍到的弱一致性事务使用Seata的AT模式,对应的是org.apache.shardingsphere.transaction.base.seata.at.SeataATShardingTransactionManager
    当然Seata也是支持XA事务,如果后续改写的话,可以通过SPI的方式的定制

    1、添加依赖

    使用XA事务需要添加一个依赖,如下:

    1. <!-- 使用XA事务时,需要引入此模块 -->
    2. <dependency>
    3. <groupId>org.apache.shardingsphere</groupId>
    4. <artifactId>sharding-transaction-xa-core</artifactId>
    5. </dependency>

    可以看到这个依赖中内置了ATOMIKOS,如下:
    一个注解搞定分布式事务 - 图2

    2、配置事务管理器

    使用事务之前当然需要配置一个事务管理器,这里和Spring Boot 中配置没差别,如下:

    1. @Configuration
    2. @EnableTransactionManagement
    3. public class TransactionConfiguration {
    4. @Bean
    5. public PlatformTransactionManager txManager(final DataSource dataSource) {
    6. return new DataSourceTransactionManager(dataSource);
    7. }
    8. }

    3、@ShardingTransactionType注解

    想要开启XA分布式事务还需要使用一个注解@ShardingTransactionType,其中的value属性的值如下:

  7. **TransactionType.LOCAL**:开启本地事务的支持,默认值

  8. **TransactionType.XA**:开启XA事务的支持
  9. **TransactionType.BASE**:开启弱事务的支持

那么显然这里只需要配置TransactionType.XA就能开启XA事务的支持
伪代码如下:

  1. @ShardingTransactionType(value = TransactionType.XA)
  2. @Transactional
  3. public void method(){
  4. //跨库操作
  5. ..............
  6. }

4、启动测试

需要注意的是Atomikos会在项目的logs目录下生成xa_tx.log文件,其中记录了事务日志,在XA崩溃恢复时所需要的日志,一定不要删除
一个注解搞定分布式事务 - 图3
对于Atomikos的一些配置可以通过在项目的classpath中添加jta.properties来定制化Atomikos配置项。