一、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官网文档地址,心愿大家多多反对和关注。