innodb_support_xa可以开关InnoDB的xa两段式事务提交。默认情况下,innodb_support_xa=true,支持xa两段式事务提交。此时MySQL首先要求innodb prepare,对应的redolog 将写入log buffer;如果有其他的引擎,其他引擎也需要做事务提交的prepare,然后MySQL server将binlog将写入;并通知各事务引擎真正commit;InnoDB将commit标志写入,完成真正的提交,响应应用程序为提交成功。这个过程中任何出错将导致事务回滚,响应应用程序为提交失败。也就是说,在这种情况下,基本不会出错。

但是由于xa两段式事务提交导致多余flush等操作,性能影响会达到10%,所有为了提高性能,有些DBA会设置innodb_support_xa=false。这样的话,redolog和binlog将无法同步,可能存在事务在主库提交,但是没有记录到binlog的情况。这样也有可能造成事务数据的丢失。

-----------------------------------------------------------------------------------
     从官方解释来看,innodb_support_xa的作用是分两类:第一,支持多实例分布式事务(外部xa事务),这个一般在分布式数据库环境中用得较多。第二,支持内部xa事务,说白了也就是说支持binlog与innodb redo log之间数据一致性。今天的重点是讨论第二类内部xa事务。
        首先我们需要明白为什么需要保持binlog与redo log之间数据一致性,这里分两个方面来解释:
第一,保证binlog里面存在的事务一定在redo log里面存在,也就是binlog里不会比redo log多事务(可以少,因为redo log里面记录的事务可能有部分没有commit,这些事务最终可能会被rollback)。先来看这样一个场景(后面的场景都是假设binlog开启):在一个AB复制环境下主库crash,然后进行crash recovery,此时如果binlog里面的的事务信息与redo log里面的信息不一致,那么就会出现主库利用redo log进行恢复后,然后binlog部分的内容复制到从库去,然后出现主从数据不一致状态。所以需要保证binlog与redo log两者事务一致性。
第二,保证binlog里面事务顺序与redo log事务顺序一致性。这也是很重要的一点,假设两者记录的事务顺序不一致,那么会出现类似于主库事务执行的顺序是ta, tb, tc,td,但是binlog里面记录的是ta,tc, tb, td,binlog复制到从库后导致主从的数据不一致。当然也由于当初蹩脚的设计导致BGC被打破,这里就不详说了。
        为了达到上面说的两点,mysql是怎么来实现的呢?没错,答案是内部xa事务(核心是2pc)。现在mysql内部一个处理流程大概是这样:
1. prepare ,然后将redo log持久化到磁盘
2. 如果前面prepare成功,那么再继续将事务日志持久化到binlog
3. 如果前面成功,那么在redo log里面写上一个commit记录
那么假如在进行着三步时又任何一步失败,crash recovery是怎么进行的呢? 此时会先从redo log将最近一个检查点开始的事务读出来,然后参考binlog里面的事务进行恢复。如果是在1 crash,那么自然整个事务都回滚;如果是在2 crash,那么也会整个事务回滚;如果是在3 crash(仅仅是commit记录没写成功),那么没有关系因为2中已经记录了此次事务的binlog,所以将这个进行commit。所以总结起来就是redo log里凡是prepare成功,但commit失败的事务都会先去binlog查找判断其是否存在(通过XID进行判断,是不是经常在binlog里面看到Xid=xxxx?这就是xa事务id),如果有则将这个事务commit,否则rollback。
        在这三个步骤中因为持久化需求每一步都需要fsync,但是如果真的每一步都需要fsync,那么sync_binlog与innodb_flush_log_at_trx_commit两个参数的意义又在哪?这里还没理得很清楚,希望自己以后补上来或是谁帮忙解答一下。
        前面已经解释完了通过内部xa事务来保证binlog里记录的事务不会比redo log多(也可以间接的理解为binlog一定只记录提交事务),这么做的原因是为了crash recovery后主从保持一致性。接下来解释目前是怎么来保证binlog与redo log之间顺序一致的。
        为什么要保证binlog里事务与redo log里事务顺序一致性原因前面已经解释过。为了保证这一点带来的问题相信了解过BGC的朋友都知道----臭名昭著的prepare_commit_mutex,没错就是它导致了正常情况下无法实现BGC,原理是什么?在每次进行xa事务时,在prepare阶段事务先拿到一个全局的prepare_commit_mutex, 然后执行前面说的持久化(fsync)redo log与binlog,然后等fsync完了之后再释放prepare_commit_mutex,这样相当于串行化的效果虽然保证了binlog与redo log之间顺序一致性,但是却导致每个事务都需要一个fsync操作,而大家都知道在一次持久化的过程中代价最大的操作就是fsync了,而想write()这些不落地的操作代价相对来说就很小。所以BGC得核心在于很多事务需要的fsync合并成一个fsync去做。
         说了这么多就只为了解释innodb_support_xa=1的价值在哪,但是刚才也说了由于xa事务中需要多次fsync,所以开启后会对性能有一定影响。从percona博客上看到06年他们测试时开启后tps下降一半,但是我实际用mysql-5.5.12+sysbench-0.5+10块SAS(raid 10)测试结果性能下面没那么明显。在oltp模式下tps几乎没差别,不过它默认读写比例是4:1,后来换成纯update测试,开始xa事务性能下降也仅仅是5%左右,没有传说中那么大的差别。所以我怀疑可能的原因有两个:第一,现在的mysql性能相对于06有了较大提升;第二,我测试的机器较好(10块SAS盘做raid10),这样即使开启了xa事务,需要较多的fsync,但是由于存储方面能抗住,所以没有体现出太大的劣势。
        接下来顺便谈一下innodb_flush_log_at_trx_commit意义以及合理设置。innodb_flush_log_at_trx_commit有0、1、2三个值分别代表不同的使redo log落地策略。0表示每秒进行一次flush,但是每次事务commit不进行任何操作(每秒调用fsync使数据落地到磁盘,不过这里需要注意如果底层存储有cache,比如raid cache,那么这时也不会真正落地,但是由于一般raid卡都带有备用电源,所以一般都认为此时数据是安全的)。1代表每次事务提交都会进行flush,这是最安全的模式。2表示每秒flush,每次事务提交时不flush,而是调用write将redo log buffer里面的redo log刷到os page cache。
        那现在来比较三种策略的优劣势:1由于每次事务commit都会是redo log落地所以是最安全的,但是由于fsync的次数增多导致性能下降比较厉害。0表示每秒flush,每次事务提交不进行任何操作,所以mysql crash或者os crash时会丢失一秒的事务。2相对于0来说了多了每次事务commit时会有一次write操作,此时数据虽然没有落地到磁盘但是只要没有 os crash,即使mysql crash,那么事务是不会丢失的。2相对于0来说会稍微安全一点点。
        所以关于这两个参数,我的建议是主库开始innodb_support_xa=1,从库不开(因为从库一般不会记binlog),数据一致性还是很重要的。而对于innodb_flush_log_at_trx_commit,除非是对数据很重要,不能丢事务,否则我建议设置成2。我看到有些公司设置成0。其实我个人认为都设置成0了就没有多少理由不设置成2,因为2带来的性能损耗是每个事务一个write操作,write操作的开销相对于fsync还是小很多的,但是这点开销换来了即使mysql挂掉事务依然不会丢的好处。

了解innodb_support_xa(分布式事务)的更多相关文章

  1. MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】

    概念: XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口.XA为了实现分布 ...

  2. JTA 使用 MySQL 分布式事务

    假定在MySQL实例1上有表 create table person( id int, name ) ) MySQL实例2上也有一张同样的表,现在从实例1中的 person 表中删除一条数据,并把这条 ...

  3. 了解一下Mysql分布式事务及优缺点、使用案例(php+mysql)

    在开发中,为了降低单点压力,通常会根据业务情况进行分表分库,将表分布在不同的库中(库可能分布在不同的机器上),但是一个业务场景可能会同时处理两个表的操作.在这种场景下,事务的提交会变得相对复杂,因为多 ...

  4. 群集中的MS DTC分布式事务协调器

    MS DTC在大多数SQL 服务器下都需要安装,若只是安装数据库引擎或Analysis 服务可不安装DTC.如果后需要使用分布式事务,则可在SQL Server群集安装完成后再安装DTC. 一.群集M ...

  5. 事务使用中如何避免误用分布式事务(System.Transactions.TransactionScope)

    1:本地事务DbTransaction和分布式事务TransactionScope的区别: 1.1:System.Data.Common.DbTransaction: 本地事务:这个没什么好说了,就是 ...

  6. 没有活动事务 链接服务器的 OLE DB 访问接口 "SQLNCLI" 无法启动分布式事务

    在windows2003下执行分布式事务的时候出现如下情况. 一. 问题现象在执行分布式事务时,在sql server 2005下收到如下错误: 链接服务器"xxxxxxx"的 O ...

  7. 已禁用对分布式事务管理器(MSDTC)的网络访问的解决方法之一

    C# ASP.NET项目提示上述错误,在代码中使用分布式事务提示添加或修改到数据库的时候.添加数据到数据库时,不会设置实体类的主键字段.

  8. 【转】PostgreSQL分布式事务配置

    XA是open group提出的分布式事务处理规范,JTA支持XA规范,JTA只规定了接口,有些应用容器提供实现,也有一些三方的开源实现可用,比如Atomikos. 如果PostgreSQL参与分布式 ...

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

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

随机推荐

  1. win10下ASP.NET Core 2.0部署环境搭建(转)

    此文用于记录在win10环境下,新建的Asp.net Core 2.0 Web应用项目如何运行在IIS上 一.运行环境 操作系统: Window10 家庭中文版 版本 10.0.15063 版本 15 ...

  2. QString 和char数组转换(转)

    在qt开发过程中经常遇到QString类和char数组进行转换,在此记录一下: QString->char数组 1 2 3 QString str="12fff"; QByt ...

  3. 客户端用javascript获取grid的数据。

  4. mySQL 教程 第5章 插入 更新与删除数据

    使用SQL Manager管理工具连接到schoolDB.由于三张表都设置了主键,因此,以下练习中插入的记录,主键不能重. 插入数据 1. 练习:为表的所有字段插入数据 为表中所有字段插入数据,可以不 ...

  5. C# 中的 enum(枚举) 类型使用例子

    一.需要根据数字获取中文名称,C# 代码里面出现if 或switch 判断语句,比如下面的类为test1.class //获取计算类型的值 string AggregateType = string. ...

  6. DCNN相关算法资料

    https://blog.csdn.net/hjimce/article/details/49955149 讲的很详细

  7. 禁止Grid、TreeGrid列排序和列菜单

    Ext的Grid和Treegrid默认提供列菜单的功能,在列菜单中可以进行排序以及控制列显示状态. 在实际项目中,往往有些列是不需要用户看到的,因此就必须屏蔽列菜单的功能. 1.屏蔽Grid,包括Ed ...

  8. 轻松理解execl系列函数

    execl函数功能如下:启动一个可执行文件,并且对他进行传送参数.一些原型如下 #include <unistd.h> extern char **environ; int execl(c ...

  9. java获取随机密码

    import java.util.Random; public class tests { /** * * author LiuQiang * date 2013-10-14 下午01:13:54 * ...

  10. -Java-Runoob-高级教程-实例-数组:09. Java 实例 – 数组扩容

    ylbtech-Java-Runoob-高级教程-实例-数组:09. Java 实例 – 数组扩容 1.返回顶部 1. Java 实例 - 数组扩容  Java 实例 以下实例演示了如何在数组初始化后 ...