MySQL中的XA协议
有一个名叫X/Open的组织提出了一个名为XA的规范。这个XA规范提出了2个角色:
- 一个全局事务由多个小的事务组成,所以我们得在某个地方找一个总揽全局的角色用于和各个小事务进行沟通,指导它们是提交还是回滚。这个角色被称作事务协调器(Transaction Coordinator)。
- 管理一个小事务的角色被称作事务管理器(Transaction Manager)。
要提交一个全局事务,那么属于该全局事务的若干个小事务就应该全部提交,只要有任何一个小事务无法提交,那么整个全局事务就应该全部回滚。XA规范中指出,要提交一个全局事务,必须分为2步:
- Prepare阶段:当协调器准备提交一个全局事务时,会依次通知各个管理器把在事务执行过程中所产生的数据都刷盘。
- Commit阶段:如果在Prepare阶段各个管理器都完成了数据的刷盘,那么协调器就要真正通知各个管理器去提交事务了,否则就需要让这些管理器回滚事务了。
XA规范把上述全局事务提交时所经历的两个阶段称作两阶段提交。在单个MySQL实例中,将server层作为事务协调器,存储引擎作为事务管理器,故本文将binlog作为事务协调器。
sql执行流程
sql提交到MySQL时需要进行词法语法分析、优化(如果没有命中索引,就会扫全表),才会执行:
sql执行流程
事务执行流程
假设我们要更新一条数据,语句如下:
update T set c=c+1 where ID=2;
如果没有两阶段提交
redolog未写入,binlog未写入:此时MySQL异常重启无法恢复数据,认为sql就没执行。
redolog写入,binlog未写入:此时MySQL异常重启能根据redolog恢复事务提交时的数据,但binlog没有记录,后续使用binlog恢复临时库会出现数据丟失,导致状态不一致。
binlog写入,redolog未写入:此时MySQL异常重启临时库能根据binlog重放事务提交时的数据,但redolog没有记录,如果主库有一些脏页已经刷盘,本应先回滚再通过binlog重放,但现在无法回滚,会导致状态不一致。
结论
所谓两阶段提交,就是指同时将redolog和binlog都写成功,这样既能保证通过binlog恢复临时库时和主库无差异,又能保证通过redolog恢复主库时和临时库无差异。