上一篇文章我介绍了在关闭binlog的情况下,事务提交的大概流程。之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称之为内部xa事务(Distributed Transactions),与之对应的还有一个外部xa事务。内部xa事务我理解主要是mysql内部为了保证binlog与redo log之间数据的一致性而存在的,这也是由其架构决定的(binlog在mysql层,而redo log 在存储引擎层);而外部xa事务则是指支持多实例分布式事务,这个才算是真正的分布式事务。既然是xa事务,必然涉及到两阶段提交,对于内部xa而言,同样存在着提交的两个阶段。下文会结合源码详细解读内部xa的两阶段提交过程,以及各种情况下,mysqld crash后,mysql如何恢复来保证事务的一致性。

测试环境:
OS:windows
DB:mysql 5.6.12
engine:innodb
 
配置文件参数:
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;
 
测试前置条件:
create table tt(col1 int, col2 varchar(100));
 
测试语句:
insert into tt values(1, 'abcdef');
commit;
 
     打开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页的状态,置为TRX_UNDO_TO_FREE或TRX_UNDO_TO_PURGE;  // trx_undo_set_state_at_finish调用

3.记录事务对应的binlog偏移,写入系统表空间; //trx_sys_update_mysql_binlog_offset调用

    
    下面这部分是我抽象出来的源码调用部分,大家可以通过单步调试方式,在关键函数中设置断点,来详细了解这个过程。
===========
 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段的标记为TRX_UNDO_PREPARED
                2.设置事务状态为TRX_STATE_PREPARED
                3.trx_flush_log_if_needed  //将产生的redolog刷入磁盘

            }
     }
     
============
commit阶段
============
MYSQL_BIN_LOG::commit
    ordered_commit
   {
1.FLUSH_STAGE
        flush_cache_to_file  //  刷binlog
 
2.SYNC_STAGE
        sync_binlog_file    //Call fsync() to sync the file to disk.
 
3.COMMIT_STAGE
        ha_commit_low
        {
            binlog_commit
            innobase_commit   
                trx_commit(trx) 
                {
                    trx_write_serialisation_history(trx, mtr);  //更新binlog位点,设置undo状态
                    trx_commit_in_memory(trx, lsn); //释放锁资源,清理保存点列表,清理回滚段
                }        
        } 
    }
 
      mysqld可能在任何情况下crash,os也有可能出现问题,另外若机器掉电,mysqld也会同样挂掉。但是即使这样,mysql仍然能保证数据库的一致性。接下来,我会结合上述流程,分析二阶段提交如何保证这点的。下面给出几种常见的场景,
1.prepare阶段,redo log落盘前,mysqld crash
2.prepare阶段,redo log落盘后,binlog落盘前,mysqld crash
3.commit阶段,binlog落盘后,mysqld crash
      对于第一种情况,由于redo没有落盘,毫无疑问,事务的更新肯定没有写入磁盘,数据库的一致性受影响;对于第二种情况,这时候redo log写入完成,但binlog还未写入,事务处于TRX_STATE_PREPARED状态,这是提交还是回滚呢?对于第三种情况,此时,redo log和binlog都已经落盘,只是undo状态没有更新,这种情况也应该提交,因为redo log和binlog已经一致了,当然这只是我的假设,需要通过源码逻辑来验证。
     下面给出了mysqld异常重启后的执行逻辑以及关键的源代码。对于第三种情况,我们可以搜集到未提交事务的binlog event,所以需要提交,与我们假设相符;而对于第二种情况,由于binlog未写入,需要通过执行回滚操作来保证数据库的一致性。
 
异常重启后,如何判断事务该提交还是回滚
1.读binlog日志,获取崩溃时没有提交的event;  //info->commit_list中含有该元素
2.若存在,则对应的事务要提交;否则需要回滚。
 
判断事务提交或回滚源码如下:
 
 
     上面讨论了两阶段提交的基本流程,以及服务器异常crash后,mysql如何重启恢复保证binlog和数据的一致性。简而言之,对于异常的xa事务,若binlog已落盘,则事务应该提交;binlog未落盘,则事务就应该回滚。由于这块涉及到的源代码较多,我也没有看完所有源代码,如有不正确的地方,欢迎指正。
 
//异常重启后,回滚流程
innobase_rollback_by_xid
    rollback_by_xid
trx_rollback_resurrected
    trx_rollback_active
        row_undo
        {
            //从回滚页获取undo记录
            //分析undo记录类型
            if (insert)
                row_undo_ins
            else
                row_undo_mod
        }
 
//异常重启后,提交流程
commit_by_xid
    trx_commit_for_mysql
 
//写binlog接口
handler.cc:binlog_log_row
sql/binlog.cc:commit
mysys/my_sync:my_sync
sql/binlog.cc:sync_binlog_file
handler/ha_innodb.cc:innobase_xa_prepare

mysql源码解读之事务提交过程(二)的更多相关文章

  1. mysql源码解读之事务提交过程(一)

    mysql是一种关系型数据库,关系型数据库一个重要的特性就是支持事务,这是区别于no-sql产品的一个核心特性.当然了,no-sql产品支持键值查询,不能支持sql语句,这也是一个区别.今天主要讨论下 ...

  2. Spring Ioc源码分析系列--Bean实例化过程(二)

    Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...

  3. mysql源码解读之配置文件

    要研究mysql,最好的资源莫过于源码了,所以本人打算通过调试源码的方式来深入理解mysql的点点滴滴.搭建mysql调试环境很简单,从官方下载mysql源码,利用cmake工具生成工程即可.为了方便 ...

  4. MySQL源码之两阶段提交

    在双1的情况下,两阶段提交的过程 环境准备:mysql 5.5.18, innodb 1.1 version配置: sync_binlog=1 innodb_flush_log_at_trx_comm ...

  5. .NET框架源码解读之SSCLI编译过程简介

    前文演示了编译SSCLI最简便的方法(在Windows下): 在“Visual Studio 2005 Command Prompt”下,进入SSCLI的根目录: 运行 env.bat 脚本准备环境: ...

  6. storm源码分析之topology提交过程

    storm集群上运行的是一个个topology,一个topology是spouts和bolts组成的图.当我们开发完topology程序后将其打成jar包,然后在shell中执行storm jar x ...

  7. Python Web Flask源码解读(三)——模板渲染过程

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  8. mybatis源码解读(四)——事务的配置

    上一篇博客我们介绍了mybatis中关于数据源的配置原理,本篇博客介绍mybatis的事务管理. 对于事务,我们是在mybatis-configuration.xml 文件中配置的: 关于解析 < ...

  9. MYSQL 源码解读系列 [线程池。。] ----dennis的博客

    http://blog.sina.com.cn/s/articlelist_1182000643_0_1.html

随机推荐

  1. SSH服务器与Android通信(1)--服务器端发送数据

    很多应用要求SSH服务器不仅和PC通信,还要和Android移动设备通信,这时就需要用到JSON了.其基本原理是服务器将数据转换成JSON格式,发送给Android客户端,客户端再将JSON格式的数据 ...

  2. SSH实例(7)

    运行结果. 浏览课程: 添加课程: 还有删除课程,这里就不演示了.

  3. 如何改变 FMX ListView 颜色

    需求:改变 ListView 颜色 适用:Firemonkey 任何平台 操作:Style 是改变控件外观最便捷的途径,ListView 也不例外,下面示范使用 StyleBook 来设定 ListV ...

  4. 关于OpenCart的一个小建议

    OpenCart是一套老牌的开源自由B2C电商系统,最近watch了其托管在在github上的项目,发现还是很活跃的,每天都有人反馈bug. 初步的看一下,它是支持在后台管理多个店铺的,而且可以同一个 ...

  5. Data Structures/Algorithms 小甲鱼99讲笔记系列(1~~15讲)

    参考资料地址: http://www.icoolxue.com/ 1.数据结构中四种逻辑结构. ① 集合 集合中任何两个数据元素之间都没有逻辑关系,组织形式松散. ② 线性结构 线性结构中的 结点按逻 ...

  6. Scalaz(45)- concurrency :Task-函数式多线程编程核心配件

    我们在上一节讨论了scalaz Future,我们说它是一个不完善的类型,最起码没有完整的异常处理机制,只能用在构建类库之类的内部环境.如果scalaz在Future类定义中增加异常处理工具的话,用户 ...

  7. [moka同学笔记]Yii2.0循环查询并对结果累加求和

    在控制器中查询好数据  $model 在视图中输入 <?php foreach($model as $key=>$r):?> <tr class="text-cent ...

  8. spring mvc+ELK从头开始搭建日志平台

    最近由于之前协助前公司做了点力所能及的事情,居然收到了一份贵重的端午礼物,是给我女儿的一个乐高积木,整个有7大包物件,我花了接近一天的时间一砖一瓦的组织起来,虽然很辛苦但是能够从过程中体验到乐趣.这次 ...

  9. Spring MVC处理异常的4种方式

    http://blog.csdn.net/ufo2910628/article/details/40399539 http://my.oschina.net/CandyDesire/blog/3333 ...

  10. word开发遇到的问题

    1.系统不能安装多个office word版本,建议只安装一个2003版本,越完整越好. 2.安装时候ghost系统会遇到问题,由于很多组件没有完整的安装,因此缺少了很多安装时文件保护要进行提醒的dl ...