概念:

XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口。XA为了实现分布式事务,将事务的提交分成了两个阶段:也就是2PC (tow phase commit),XA协议就是通过将事务的提交分为两个阶段来实现分布式事务。

两阶段:

1)prepare 阶段

事务管理器向所有涉及到的数据库服务器发出prepare"准备提交"请求,数据库收到请求后执行数据修改和日志记录等处理,处理完成后只是把事务的状态改成"可以提交",然后把结果返回给事务管理器。即:为prepare阶段,TM向RM发出prepare指令,RM进行操作,然后返回成功与否的信息给TM。

2)commit 阶段

事务管理器收到回应后进入第二阶段,如果在第一阶段内有任何一个数据库的操作发生了错误,或者事务管理器收不到某个数据库的回应,则认为事务失败,回撤所有数据库的事务。数据库服务器收不到第二阶段的确认提交请求,也会把"可以提交"的事务回撤。如果第一阶段中所有数据库都提交成功,那么事务管理器向数据库服务器发出"确认提交"请求,数据库服务器把事务的"可以提交"状态改为"提交完成"状态,然后返回应答。即:为事务提交或者回滚阶段,如果TM收到所有RM的成功消息,则TM向RM发出提交指令;不然则发出回滚指令。

实现:

MySQL中的XA实现分为:外部XA和内部XA。前者是指我们通常意义上的分布式事务实现;后者是指单台MySQL服务器中,Server层作为TM(事务协调者),而服务器中的多个数据库实例作为RM,而进行的一种分布式事务,也就是MySQL跨库事务;也就是一个事务涉及到同一条MySQL服务器中的两个innodb数据库(因为其它引擎不支持XA)。

1)内部XA的额外功能:XA 将事务的提交分为两个阶段,而这种实现,解决了 binlog 和 redo log的一致性问题。

MySQL为了兼容其它非事物引擎的复制,在server层面引入了 binlog, 它可以记录所有引擎中的修改操作,因而可以对所有的引擎使用复制功能。MySQL在4.x 的时候放弃redo的复制策略而引入binlog。但是引入了binlog,会导致一个问题——binlog和redo log的一致性问题:一个事务的提交必须写redo log和binlog,那么二者如何协调一致呢?事务的提交以哪一个log为标准?如何判断事务提交?事务崩溃恢复如何进行?

MySQL通过两阶段提交(内部XA的两阶段提交)很好地解决了这一问题:
第一阶段:InnoDB prepare,持有prepare_commit_mutex,并且write/sync redo log; 将回滚段设置为Prepared状态,binlog不作任何操作;
第二阶段:包含两步,> write/sync Binlog; > InnoDB commit (写入COMMIT标记后释放prepare_commit_mutex);
以binlog 的写入与否作为事务提交成功与否的标志,innodb commit标志并不是事务成功与否的标志。
此时的事务崩溃恢复过程如下:
> 崩溃恢复时,扫描最后一个Binlog文件,提取其中的xid
> InnoDB维持了状态为Prepare的事务链表,将这些事务的xid和Binlog中记录的xid做比较,如果在Binlog中存在,则提交,否则回滚事务。
通过这种方式,可以让InnoDB和Binlog中的事务状态保持一致。如果在写入innodb commit标志时崩溃,则恢复时,会重新对commit标志进行写入;在prepare阶段崩溃,则会回滚,在write/sync binlog阶段崩溃,也会回滚

简而言之就是:先写redo log,再写binlog,并以binlog写成功为事务提交成功的标志。崩溃恢复是以binlog中的xid和redo log中的xid进行比较,xid在binlog里存在则提交,不存在则回滚。

MySQL XA分为两类,内部XA与外部XA;

内部XA用于同一实例下跨多个引擎的事务,由Binlog作为协调者;

外部XA用于跨多个MySQL实例的分布式事务,需要应用层介入作为协调者(崩溃时的悬挂事务,全局提交还是回滚,需要由应用层决定,对应用层的实现要求较高);

最常见的内部XA事务存在于binlog与InnoDB存储引擎之间,从而保证了主从环境的数据一致性。

2)binlog 组提交:

      上面介绍事务的两阶段提交过程是5.6之前版本中的实现,有严重的缺陷。当sync_binlog=1时,很明显上述的第二阶段中的 write/sync binlog会成为瓶颈,而且还是持有全局大锁(prepare_commit_mutex: prepare 和 commit共用一把锁),这会导致性能急剧下降。解决办法就是在MySQL5.6中引进的binlog组提交。

Binlog Group Commit的过程拆分成了三个阶段

> flush stage 将各个线程的binlog从cache写到文件中;
> sync stage 对binlog做fsync操作(如果需要的话;最重要的就是这一步,对多个线程的binlog合并写入磁盘);
> commit stage 为各个线程做引擎层的事务commit(这里不用写redo log,在prepare阶段已写)。
每个stage同时只有一个线程在操作。(分成三个阶段,每个阶段的任务分配给一个专门的线程,这是典型的并发优化)
这种实现的优势在于三个阶段可以并发执行,从而提升效率。注意:prepare阶段没有变,还是write/sync redo log。
(另外:5.7中引入了MTS:多线程slave复制,也是通过binlog组提交实现的,在binlog组提交时,给每一个组提交打上一个seqno,然后在slave中就可以按照master中一样按照seqno的大小顺序,进行事务组提交了。)
题外话:淘宝对binlog group commit进行了进一步的优化,从XA恢复的逻辑我们可以知道,只要保证InnoDB Prepare阶段的redo日志在写Binlog前完成write/sync即可。因此我们对Group Commit的第一个stage的逻辑做了些许修改,大概描述如下:
. InnoDB Prepare,记录当前的LSN到thd中;
. 进入Group Commit的flush stage;Leader搜集队列,同时算出队列中最大的LSN。
. 将InnoDB的redo log write/fsync到指定的LSN (注:这一步就是redo log的组写入。因为小于等于LSN的redo log被一次性写入到ib_logfile[|]) #放到flush binlog 之后
. 写Binlog并进行随后的工作(sync Binlog, InnoDB commit , etc)

也就是将 redo log的write/sync延迟到了 binlog group commit的 flush stage 之后,sync binlog之前。通过延迟写redo log的方式,显式的为redo log做了一次组写入(redo log group write),并减少了(redo log) log_sys->mutex的竞争。也就是将 binlog group commit 对应的redo log也进行了 group write. 这样binlog 和 redo log都进行了优化。

注意:当引入Group Commit后,sync_binlog的含义就变了,假定设为1000,表示的不是1000个事务后做一次fsync,而是1000个事务组。

3)相关参数:

innodb_support_xa:默认为true,表示启用XA,虽然它会导致一次额外的磁盘flush(prepare阶段flush redo log). 但是我们必须启用,而不能关闭它。因为关闭会导致binlog写入的顺序和实际的事务提交顺序不一致,会导致崩溃恢复和slave复制时发生数据错误。如果启用了log-bin参数,并且不止一个线程对数据库进行修改,那么就必须启用innodb_support_xa参数。

文档:

http://www.ywnds.com/?p=5798

http://www.ywnds.com/?p=7892

MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】的更多相关文章

  1. 分布式事务 & 两阶段提交 & 三阶段提交

    可以参考这篇文章: http://blog.csdn.net/whycold/article/details/47702133 两阶段提交保证了分布式事务的原子性,这些子事务要么都做,要么都不做. 而 ...

  2. 聊一聊 MySQL 中的数据编辑过程中涉及的两阶段提交

    MySQL 数据库中的两阶段提交,不知道您知道不?这篇文章就简单的聊一聊 MySQL 数据库中的两阶段提交,两阶段提交发生在数据变更期间(更新.删除.新增等),两阶段提交过程中涉及到了 MySQL 数 ...

  3. 分布式事务 spring 两阶段提交 tcc

    请问分布式事务一致性与raft或paxos协议解决的一致性问题是同一回事吗? - 知乎 https://www.zhihu.com/question/275845393 分布式事务11_TCC 两阶段 ...

  4. 分布式事务、XA、两阶段提交、一阶段提交

    本文原文连接:http://blog.csdn.net/bluishglc/article/details/7612811 ,转载请注明出处! 1.XA XA是由X/Open组织提出的分布式事务的规范 ...

  5. 分布式事务(一)两阶段提交及JTA

    原创文章,同步发自作者个人博客 http://www.jasongj.com/big_data/two_phase_commit/ 分布式事务 分布式事务简介 分布式事务是指会涉及到操作多个数据库(或 ...

  6. 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究 转载

    1.XA XA是由X/Open组织提出的分布式事务的规范.XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接 ...

  7. XA: 事务和两阶段提交

    本文原文连接:http://blog.csdn.net/bluishglc/article/details/7612811 ,转载请注明出处! 1.XA XA是由X/Open组织提出的两阶段提交协议, ...

  8. 全网最牛X的!!! MySQL两阶段提交串讲

    目录 一.吹个牛 二.事务及它的特性 三.简单看下两阶段提交的流程 四.两阶段写日志用意? 五.加餐:sync_binlog = 1 问题 六.如何判断binlog和redolog是否达成了一致 七. ...

  9. 两阶段提交及JTA

    两阶段提交及JTA 分布式事务 分布式事务简介 分布式事务是指会涉及到操作多个数据库(或者提供事务语义的系统,如JMS)的事务.其实就是将对同一数据库事务的概念扩大到了对多个数据库的事务.目的是为了保 ...

随机推荐

  1. Javabean+servlet+JSP(html)实例应用

    大家都知道Javabean+servlet+JSP是最简单的MVC模式.的确,在一个小型的项目中,这个模式完全够用. 它优雅并且简洁.加上jQueryui的完美展示效果,让这个模式看起来非常合适.当然 ...

  2. default配置

    log_format main '$remote_addr - $remote_user [$time_local] $request ' '"$status" $body_byt ...

  3. PHP单一入口apache配置和去除index.php

    index : index在互联网上表示网站的默认主页. 一般为 index.html index.htm index.asp index.php: 另外的默认主页也多用default.html;de ...

  4. hdu 4960 Another OCD Patient (最短路 解法

    http://acm.hdu.edu.cn/showproblem.php?pid=4960 2014 Multi-University Training Contest 9 Another OCD ...

  5. R-处理数据对象的实用函数

  6. block 块函数

    定义模块函数: <?php function smarty_block_text($args,$content,$smarty,$a) { $color=$args["color&qu ...

  7. Swift2.1 语法指南——协议

    原档: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programm ...

  8. php面向对象面试题

    php面试题之四--PHP面向对象(基础部分) 四.PHP面向对象 1. 写出 php 的 public.protected.private 三种访问控制模式的区别(新浪网技术部) public:公有 ...

  9. Mac os壁纸提取

    想必用过Mac os系统的朋友都知道mac壁纸,提取出来用作壁纸是十分好看的 下面给出壁纸的位置,自己用文件管理器打开然后复制出来即可! 系统盘:/Library/DesktopPictures

  10. View和ViewImage设置图片

    1.view类的设置背景android:background --setBackgroundResource(int) --A drawable to use as the background. s ...