mysql xa 事务理解
在 MySQL 中,XA 事务的预提交阶段(Prepare Phase) 会通过执行 XA PREPARE
语句将事务标记为 准备提交 状态。此时事务的数据修改已被持久化,但尚未最终提交,需等待全局事务协调器的最终决策(提交或回滚)。
XA 事务的完整流程
XA 事务分为两阶段提交(Two-Phase Commit, 2PC):
- 准备阶段(Prepare Phase):所有参与者(如 MySQL 实例)将事务持久化,并返回是否可提交。
- 提交阶段(Commit Phase):全局事务协调器根据参与者反馈,决定提交或回滚事务。
MySQL 中 XA 事务的具体操作
1. 开启 XA 事务
XA START 'transaction_id'; -- 启动一个 XA 事务,transaction_id 是全局唯一标识
2. 执行数据操作(DML)
INSERT INTO orders (order_id, amount) VALUES (1001, 99.99);
UPDATE accounts SET balance = balance - 99.99 WHERE user_id = 1;
3. 结束 XA 事务
XA END 'transaction_id'; -- 结束当前 XA 事务
4. 预提交(Prepare Phase)
XA PREPARE 'transaction_id'; -- 关键操作:将事务标记为准备提交
此时 MySQL 会:
- 将事务的修改写入 Redo Log(确保崩溃恢复能力)。
- 事务进入
PREPARED
状态,等待协调器指令。 - 数据行仍持有锁(如行锁、间隙锁),其他事务无法修改。
查看预提交状态的事务
XA RECOVER; -- 列出所有处于 PREPARED 状态的 XA 事务
输出示例:
+--------------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+--------------+--------------+--------------+------+
| 0 | 4 | 0 | tx1 | -- data 列显示事务 ID
+--------------+--------------+--------------+------+
最终提交或回滚
- 提交:
XA COMMIT 'transaction_id'; -- 最终提交事务
- 回滚:
XA ROLLBACK 'transaction_id'; -- 回滚事务
整体sql示例
XA START 'xatest';
INSERT INTO seata_order.order_tbl (user_id,commodity_code,count,money,status) VALUES
('1','product-1',1,5,NULL);
XA END 'xatest';
XA PREPARE 'xatest';
XA COMMIT 'xatest'
XA ROLLBACK 'xatest';
预提交阶段的关键行为
行为 | 说明 |
---|---|
数据持久化 | 修改写入 Redo Log,确保即使 MySQL 崩溃也能恢复 |
锁保持 | 事务涉及的锁在 PREPARED 状态持续生效,防止其他事务修改数据 |
事务状态记录 | 事务 ID 和状态信息存储在内存和磁盘(mysql.xa_prepared_log ) |
协调器依赖 | 事务需等待外部协调器调用 XA COMMIT 或 XA ROLLBACK 才能结束 |
应用场景
- 跨数据库事务:如同时操作 MySQL 和 Oracle。
- 微服务分布式事务:通过 Seata、Atomikos 等框架协调多服务事务。
- 数据最终一致性:确保多个操作要么全部成功,要么全部回滚。
注意事项
- 超时处理:
- 若协调器长时间未提交,
PREPARED
事务可能阻塞资源。需设置超时机制。
- 若协调器长时间未提交,
- 崩溃恢复:
- MySQL 重启后会自动恢复
PREPARED
状态的事务,需人工介入处理。
- MySQL 重启后会自动恢复
- 性能影响:
- XA 事务比普通事务开销更大,谨慎用于高频场景。
通过 XA PREPARE
,MySQL 实现了分布式事务的关键一步,确保事务在最终提交前具备原子性和持久性。