浅析innodb_support_xa与innodb_flush_log_at_trx_commit

重大字:mysql源码解读之事务提交进程–第二篇

 

上一篇小说笔者介绍了在关闭binlog的情状下,事务提交的光景流程。之所以关闭binlog,是因为开启binlog后工作提交换程会造成两等第提交,这里的两品级提交并不涉及分布式事务,当然mysql把它称作内部xa事务(Distributed
Transactions),与之对应的还应该有三个表面xa事务。内部xa事务作者领悟首借使mysql内部为了保障binlog与redo
log之间数据的一致性而存在的,那也是由其架构决定的(binlog在mysql层,而redo
log
在蕴藏引擎层);而外界xa事务则是指援助多实例布满式事务,这些才总算真正的布满式事务。既然是xa事务,必然涉及到两等级提交,对于里边xa来讲,同样存在着提交的八个阶段。下文种结合源码详细解读内部xa的两等第提交进程,以及种种场合下,mysqld
crash后,mysql怎样恢复生机来担保职业的一致性。

   
很久在此以前对innodb_support_xa存在一些误解,当初径直以为innodb_support_xa只调节外界xa事务,内部的xa事务是mysql内部实行调节,无法人工干预(这里说的里边xa事务主如果指binlog与innodb的redo
log保持一致性所使用的内部xa事务)。直到前阵子在果壳网络来看有人探讨mysql数据安全时才留心去手册上查看了有关innodb_support_xa的演讲,近些日子又与同事又一次探究了这几个难题,于是想着照旧将其记录下来。先看官方手册上对innodb_support_xa的解释:

测验情况:
OS:windows
DB:mysql 5.6.12
engine:innodb

“EnablesInnoDBsupport for two-phase commit in XA transactions, causing
an extra disk flush for transaction preparation. This set-ting is the
default. The XA mechanism is used internally and is essential for any
server that has its binary log turned on and is accepting changes to its
data from more than one thread. If you turn it off, transactions can be
written to the binary log in a different order from the one in which the
live database is committing them. This can produce different data when
the binary log is replayed in disaster recovery or on a replication
slave. Do not turn it off on a replication master server unless you have
an unusual setup where only one thread is able to change data.”

配置文件参数:
log-bin=D:\chuck\mysql\log\5-6-12\mysql-bin
binlog_format=ROW
set autocommit=0;
sync_binlog=1;
innodb_flush_log_at_trx_commit=1;
innodb_support_xa=1;

从官方解释来看,innodb_support_xa的法力是分两类:第一,协理多实例布满式事务(外部xa事务),这几个貌似在布满式数据库情状中用得较多。第二,帮衬内部xa事务,说白了也等于说帮忙binlog与innodb
redo log之间数据一致性。今日的基本点是座谈第二类内部xa事务。

测量检验前置条件:
create table tt(col1 int, col2 varchar(100));

        首先我们供给通晓怎么须求有限帮忙binlog与redo
log之间数据一致性,这里分五个方面来分解:

测验语句:
insert into tt values(1, ‘abcdef’);
commit;

率先,有限支撑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选项后,推行职业提交命令时,就能够进入两等第提交方式。两品级提交分为prepare阶段和commit多个级次。流程如下
:这当中涉及到多个重大的参数:innodb_flush_log_at_trx_commit和sync_binlog,参数能够设置分裂的值,具体能够查阅mysql的相帮手册。小编那边设置的是双一方式(innodb_flush_log_at_trx_commit=1,sync_binlog=1),差别的形式不同在于,写文件调用write和落盘fsync调用的功能差别,所产生的结果是mysqld
或 os
crash后,不严厉的装置恐怕会丢掉事务的翻新。双一格局是最严厉的形式,这种装置情形下,单机在任何景况下不会丢掉事务更新。
prepare阶段:
    1.设置undo state=TRX_UNDO_PREPARED;
//trx_undo_set_state_at_prepare调用
    2.刷作业更新产生的redo日志;【步骤1产生的redo日志也会刷入】
   
commit阶段:
   1.将业务产生的binlog写入文件,刷入磁盘;
   2.装置undo页的情形,置为T冠道X_UNDO_TO_FREE或TRX_UNDO_TO_PURGE;  //
trx_undo_set_state_at_finish调用
   3.笔录事务对应的binlog偏移,写入系统表空间;
//trx_sys_update_mysql_binlog_offset调用
   
   

第二,保障binlog里面工作逐项与redo
log事务逐项一致性。那也是很关键的少数,借使两个记录的业务逐项分化等,那么会并发类似于主库事务实行的各样是ta,
tb, tc,td,可是binlog里面著录的是ta,tc, tb,
td,binlog复制到从库后促成基本的数量不雷同。当然也鉴于当年不善的准备导致BGC被打破,这里就一窍不通说了。

上边这一部分是笔者抽象出来的源码调用部分,大家能够经过单步调节和测验形式,在主要函数中设置断点,来详细了然这几个进度。

       
为了完毕地点说的两点,mysql是怎么来达成的呢?没有错,答案是中间xa事务(核心是2pc)。以往mysql内部叁个甩卖流程差不离是那般:

prepare阶段

MYSQL_BIN_LOG::prepare
    ha_prepare_low
    {
engine:
binlog_prepare
innobase_xa_prepare
mysql:
trx_prepare_for_mysql
{
                1.trx_undo_set_state_at_prepare   
//设置undo段的符号为T劲客X_UNDO_PREPARED
                2.装置专门的职业状态为T纳瓦拉X_STATE_PREPARED
4503.com,                3.trx_flush_log_if_needed 
//将发生的redolog刷入磁盘
            }
     }

  1. prepare ,然后将redo log长久化到磁盘

  2. 如若近些日子prepare成功,那么再持续将专门的学问日志悠久化到binlog

  3. 万一前方成功,那么在redo log里面写上四个commit记录