一、XA 是什么?
XA 协定本就是为一个分布式事务协定,它规定了 XA PREPARE、XA COMMIT、XA ROLLBACK 等命令。XA 协定规定了事务管理器(协调者)和资源管理器(数据节点)如何交互,共同完成分布式 2PC 的过程
XA 次要规定了 RM 与 TM 之间的交互,上面来看下 XA 标准中定义的 RM 和 TM 交互的接口:
-
xa_start 负责开启或者复原一个事务分支,并且治理 XID 到调用线程
- xa_end 负责勾销以后线程与事务分支的关联
- xa_prepare 负责询问 RM 是否筹备好了提交事务分支
- xa_commit 告诉 RM 提交事务分支
- xa_rollback 告诉 RM 回滚事务分支
XA 协定是应用了二阶段协定的,其中:
第一阶段 TM 要求所有的 RM 筹备提交对应的事务分支,询问 RM 是否有能力保障胜利的提交事务分支,RM 依据本人的状况,如果判断本人进行的工作能够被提交,那就就对工作内容进行长久化,并给 TM 回执 OK;否者给 TM 的回执 NO。RM 在发送了否定回答并回滚了曾经的工作后,就能够抛弃这个事务分支信息了。
第二阶段 TM 依据阶段 1 各个 RM prepare 的后果,决定是提交还是回滚事务。如果所有的 RM 都 prepare 胜利,那么 TM 告诉所有的 RM 进行提交;如果有 RM prepare 回执 NO 的话,则 TM 告诉所有 RM 回滚本人的事务分支。
也就是 TM 与 RM 之间是通过两阶段提交协定进行交互的。
二、MySQL 中 XA 实现
1. 外部 XA 事务
MySQL 中只有 InnoDB 引擎反对 XA 协定,外部 XA 事务次要用来协调存储引擎和二进制日志
确认下 mysql 是否启动了 xa 性能:
测试手动执行 xa 事务:
其中首先应用 XA START‘xid’ 启动了一个 XA 事务,并把它置于 ACTIVE 状态
对于一个 ACTIVE 状态的 XA 事务,咱们能够执行形成事务的多条 SQL 语句,也就是指定分支事务的边界,而后执行一个 XA END‘xid’ 语句,XA END 把事务放入 IDLE 状态,也就是完结事务边界,在 xa start 和 xa end 之间的语句就形成了本分支事务的一个事务范畴。当调用 xa end ‘xid1’ 后因为完结了事务边界,所以这时候如果在执行 sql 语句会抛出 ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state 谬误,也就是当分支事务处于 IDLE 状态时候不容许执行没有蕴含到分支事务边界外面的其余 sql.
对于一个 IDLE 状态 XA 事务,能够执行一个 XA PREPARE 语句或一个 XA COMMIT…ONE PHASE 语句, 其中 XA PREPARE 把事务放入 PREPARED 状态。在此点上的 XA RECOVER 语句将在其输入中包含事务的 xid 值,因为 XA RECOVER 会列出处于 PREPARED 状态的所有 XA 事务。XA COMMIT…ONE PHASE 用于准备和提交事务,也就是转换为一阶段协定,间接提交事务。
对于一个 PREPARED 状态的 XA 事务, 能够执行 XA COMMIT 语句来提交或者执行 XA ROLLBACK 来回滚 xa 事务。
其中二阶段协定中第一阶段是执行 xa prepare 时候,这时候 MySQL 客户端(TM)向 MySQL 数据库服务器(RM)收回 prepare” 筹备提交 ” 申请,数据库收到申请后执行数据批改和日志记录等解决,解决实现后只是把事务的状态改成 ” 能够提交 ”, 而后把后果返回给事务管理器。
如果第一阶段中数据库都 prepare 胜利,那么 mysql 客户端(TM)向数据库服务器收回 ”commit” 申请,数据库服务器把事务的 ” 能够提交 ” 状态改为 ” 提交实现 ” 状态,而后返回应答。如果在第一阶段内数据库的操作产生了谬误,或者 mysql 客户端(RM)收不到数据库的回应,则认为事务失败,执行 rollback 回撤所有数据库的事务。
两阶段提交 PC
mysql 的两阶段提交原理
(1)perpare 阶段 写入 redo 日志
1、设置 undo state=TRX_UNDO_PREPARED;
2、刷事务更新产生的 redo 日志;
(2)commit 阶段 写入 binlog 日志
1、将事务产生的 binlog 写入文件,刷入磁盘;
2、设置 undo 页的状态, 置为 TRX_UNDO_TO_FREE 或 TRX_UNDO_TO_PURGE; // 标记能够清理回滚段
3、记录事务对应的 binlog 偏移,写入零碎表空间。
两阶段提交是跨零碎维持数据逻辑一致性时罕用的一个计划。两阶段存在阻塞难题,提出的三阶段提交,在二阶段的根底上减少了一个预提交。
(3)假如法验证为什么分两阶段:
A. 先写 redo log 后写 binlog。假如在 redo log 写完,binlog 还没有写完的时候,MySQL 过程异样重启。因为咱们后面说过的,redo log 写完之后,零碎即便解体,依然可能把数据恢复回来,所以复原后这一行 c 的值是 1。
然而因为 binlog 没写完就 crash 了,这时候 binlog 外面就没有记录这个语句。因而,之后备份日志的时候,存起来的 binlog 外面就没有这条语句。
而后你会发现,如果须要用这个 binlog 来复原长期库的话,因为这个语句的 binlog 失落,这个长期库就会少了这一次更新,复原进去的这一行 c 的值就是 0,与原库的值不同。
B. 先写 binlog 后写 redo log。如果在 binlog 写完之后 crash,因为 redo log 还没写,解体复原当前这个事务有效,所以这一行 c 的值是 0。然而 binlog 外面曾经记录了“把 c 从 0 改成 1”这个日志。所以,在之后用 binlog 来复原的时候就多了一个事务进去,复原进去的这一行 c 的值就是 1,与原库的值不同。
(4)redo 和 binlog 这两种日志有以下三点不同。
1、redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都能够应用。
2、redo log 是物理日志,记录的是“在某个数据页上做了什么批改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比方“给 ID=2 这一行的 c 字段加 1”。
3、redo log 是循环写的,空间固定会用完;binlog 是能够追加写入的。“追加写”是指 binlog 文件写到肯定大小后会切换到下一个,并不会笼罩以前的日志。
2. 内部 XA 事务
参加到内部分布式事务中(比方多个数据库实现的分布式事务),目前 mysql 对外部事务的反对还不够,这里也就不进行太多的形容了。
总结
以上就是这次对 mysqlXA 的了解和总结,次要参照 mysql 官网文档资料并退出本人的实际和了解,贴一下 mysql 官网文档地址,心愿大家多多反对和关注。