打开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事务提交过程(二)

    上一篇文章我们介绍了在关闭binlog的情况下,事务提交的大概流程.之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它 ...

  2. MySQL事务提交过程

    一.MySQL事务提交过程(一) MySQL作为一种关系型数据库,已被广泛应用到互联网中的诸多项目中.今天我们来讨论下事务的提交过程. 由于mysql插件式存储架构,导致开启binlog后,事务提交实 ...

  3. MySQL事务提交过程(一)

    MySQL作为一种关系型数据库,已被广泛应用到互联网中的诸多项目中.今天我们来讨论下事务的提交过程. MySQL体系结构 由于mysql插件式存储架构,导致开启binlog后,事务提交实质是二阶段提交 ...

  4. MySQL事务提交过程(转载)

    http://blog.csdn.net/sofia1217/article/details/53968214 上一篇文章我们介绍了在关闭binlog的情况下,事务提交的大概流程.之所以关闭binlo ...

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

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

  6. 4.事务提交过程,交易的基本概念,Oracle交易周期,保存点savepoint,数据库的隔离级别

     事务提交过程 事务 基本概念 概念:一个或者多个DML语言组成 特点:要么都成功.要么都失败 事务的隔离性:多个client同一时候操作数据库的时候.要隔离它们的操作, 否则出现:脏读  不可反 ...

  7. MySQL 事务提交 --不良好的事务习惯。

    MySQL 事务提交 --不良好的事务习惯 我们知道"事务"是数据库区别于文件系统的重要特性之一.MySQL的InnoDB引擎中的事务也完全符合ACID(原子性 一致性 隔离性 持 ...

  8. 分布式事务_03_2PC框架raincat源码解析-事务提交过程

    一.前言 前面两节,我们已经将raincat的demo工程启动,并简单分析了下事务协调者与事务参与者的启动过程. 这一节,我们来看下raincat的事务提交过程. 二.事务提交过程概览 1.二阶段对应 ...

  9. mysql源码解读之事务提交过程(二)

    上一篇文章我介绍了在关闭binlog的情况下,事务提交的大概流程.之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称 ...

随机推荐

  1. <! [if IE 神奇的条件注释 ]>

    早上起来无聊,看到某学长发的一张代码截图有条件注释,正好,研究一下. 条件注释: 在IE中用来区分IE版本.是否为IE的代码神器! 在其他的浏览器里是不好使的. 不过也值得了,IE都区分出来了,其他的 ...

  2. Oracle Study Note : Tablespace and Data Files

    1.how to create a tablespace that employs the most common features create tablespace tb_name #create ...

  3. MIFARE系列1《MIFARE简介》

    随着社会的发展,智能卡在很多领域得到了广泛的应用.特别是非接触卡,由于使用方便以及功能强大的特点,在管理.公交.工作证.身份识别等领域得到了快速的普及和推广. 非接触卡已经逐步发展成为一个独立的跨学科 ...

  4. bzoj 1269 [AHOI2006]文本编辑器editor

    原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269 伸展树的运用,如下: #include<cstdio> #include ...

  5. KnockoutJS学习笔记10:KonckoutJS foreach绑定

      KnockoutJS foreach绑定用来处理数组,通常用来将一个数组绑定到一个列表或者table中.在foreach绑定中,我们可以使用if.with等嵌套绑定. 示例代码: <tabl ...

  6. 十一、从头到尾彻底解析Hash 表算法

    在研究MonetDB时深入的学习了hash算法,看了作者的文章很有感触,所以转发,希望能够使更多人受益! 十一.从头到尾彻底解析Hash 表算法 作者:July.wuliming.pkuoliver  ...

  7. Swift TabeleViewCell dequeueReusableCellWithIdentifier 使用的新的细节,原来现在可以这样

    今天在看官方的TableView Guide,突然想起来最近写的一个代码中实现tableViewCell复用的时候有点问题: var cell = UITableViewCell(style: UIT ...

  8. (转)ZooKeeper 笔记(1) 安装部署及hello world

    ZooKeeper 笔记(1) 安装部署及hello world   先给一堆学习文档,方便以后查看 官网文档地址大全: OverView(概述) http://zookeeper.apache.or ...

  9. json 读写 swift

    // // ViewController.swift // json读写 // // Created by mac on 15/7/14. // Copyright (c) 2015年 fangyuh ...

  10. powerdesigner 技巧

    1.修改建表脚本生成规则.如果每个表格都有相同的字段,可以如下修改: Database -> Edit Current DBMS 展开 Script -> Object -> Tab ...