mysql 8.0.13+ 已彻底删除 innodb_support_xa 参数,xa 事务默认启用;关键配置是 binlog_format=row/mixed、sync_binlog=1 和 innodb_flush_log_at_trx_commit=1,且必须显式执行 xa prepare 才进入两阶段提交。

Java 中配置分布式事务的两阶段提交(2PC),核心不是“配个开关”,而是搭建符合 XA 规范的协作环境:需要支持 XA 的数据库、XA 兼容的连接池、JTA 事务管理器,以及按规范编排的事务代码。整个链条缺一不可。
数据库必须开启并验证 XA 支持
MySQL 和 PostgreSQL 是最常用场景,配置要点明确:
-
MySQL(5.0.3+,InnoDB):默认支持 XA,无需额外启用,但需确认使用的是
mysql-connector-java8.x(推荐 8.0.33+),且驱动类为com.mysql.cj.jdbc.Driver -
PostgreSQL(9.3+):需在
postgresql.conf中显式设置max_prepared_transactions = 20 # 必须 > 0,否则 PREPARE TRANSACTION 会报错
同时确保用户有
pg_prepared_statements权限 -
验证方式(以 MySQL 为例):
XA START 'test1'; INSERT INTO t1 VALUES (1); XA END 'test1'; XA PREPARE 'test1'; -- 成功即说明 XA 就绪
连接池要选支持 XA 的实现
普通 HikariCP 或 Druid 默认不支持 XA,必须换用或扩展:
-
推荐方案:用
Atomikos+AtomikosDataSourceBean或Bitronix+PoolingDataSource -
Spring Boot 示例(Atomikos):
<!-- pom.xml --> <dependency><groupid>org.springframework.boot</groupid><artifactid>spring-boot-starter-jta-atomikos</artifactid></dependency>
# application.yml spring: jta: atomikos: properties: log-base-dir: ./logs/atomikos datasource: # 不再直接配 datasource,改由 JTA 管理然后通过
@Transactional声明式启用,底层自动绑定 XA 资源。
Alibabacloud Sdk Client Initialization For Java下载在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
事务管理器要嵌入或独立部署
Java 中主流选择两类:
- 嵌入式(开发/中小规模):Atomikos、Bitronix —— 以 Jar 形式集成,零外部依赖
-
容器级(生产/高可用):JBoss Narayana、WebLogic/JBoss 自带 TM —— 需配合应用服务器
关键点:TM 必须能识别并注册所有参与者的 XADataSource,例如 Atomikos 中:@Bean public DataSource dataSource1() { AtomikosDataSourceBean ds = new AtomikosDataSourceBean(); ds.setUniqueResourceName("mysql-db"); ds.setXaDataSourceClassName("com.mysql.cj.jdbc.MysqlXADataSource"); ds.setPoolSize(5); Properties props = new Properties(); props.setProperty("url", "jdbc:mysql://localhost:3306/db1"); props.setProperty("user", "root"); props.setProperty("password", "123"); ds.setXaProperties(props); return ds; }
代码层必须走 JTA 标准流程
不能靠 connection.commit() 手动控制,必须依赖 UserTransaction 或 Spring 的 @Transactional:
-
使用声明式事务(推荐):
@Service @Transactional // 此注解由 JTA TM 解析,自动触发 prepare/commit/rollback public class TransferService { @Autowired private JdbcTemplate mysqlJdbc; @Autowired private JdbcTemplate pgJdbc; public void transfer(int amount) { mysqlJdbc.update("UPDATE account SET balance = balance - ? WHERE id = 'alice'", amount); pgJdbc.update("UPDATE account SET balance = balance + ? WHERE id = 'bob'", amount); } } 关键前提:两个
JdbcTemplate的DataSource必须是同一个 TM 管理的 XA 数据源实例,否则事务无法跨库传播。
整个链路跑通的标志是——当任意一个库在 PREPARE 阶段失败(如唯一键冲突、锁超时),另一个库的变更会被自动回滚,不会出现“扣款成功、入账失败”的不一致。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










