打开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
 
转:https://www.cnblogs.com/yuyue2014/p/4738007.html

mysql之 事务prepare 与 commit 阶段分析的更多相关文章

  1. MySQL事务-ROLLBACK,COMMIT用法详解

    使用ROLLBACK 既然我们已经知道了什么是事务处理,下面讨论事务处理的管理中所涉及的问题. 管理事务处理的关键在于将SQL语句组分解为逻辑块,并明确规定数据何时应该回退,何时不应该回退. MySQ ...

  2. Mysql分布式事务

    关于Mysql分布式事务介绍,可参考:http://blog.csdn.net/luckyjiuyi/article/details/46955337 分为两个阶段:准备和执行阶段.有两个角色:事务的 ...

  3. mysql 分布式事务

    php + mysql 分布式事务 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元: 事务应该具有4个属性:原子性.一致性.隔离性.持续性 原子性(atomicit ...

  4. mysql.connector 事务总结

    mysql.connector事务总结: connection.autocommit = 0 (默认值) 事务处理 使用 connection.commit()方法 #!/usr/bin/env py ...

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

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

  6. 一文读懂MySQL的事务隔离级别及MVCC机制

    回顾前文: 一文学会MySQL的explain工具 一文读懂MySQL的索引结构及查询优化 (同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论不一定适用于其他版本) 就软件开 ...

  7. MySQL 数据库事务与复制

    好久没有写技术文章了,因为一直在思考 「后端分布式」这个系列到底怎么写才合适. 最近基本想清楚了,「后端分布式」包括「分布式存储」和 「分布式计算」两大类. 结合实际工作中碰到的问题,以寻找答案的方式 ...

  8. mysql的事务和select...for update

    一.mysql的事务mysql的事务有两种方式:1.SET AUTOCOMMIT=0;也就是关闭了自动提交,那么任何commit或rollback语句都可以触发事务提交;如果SET AUTOCOMMI ...

  9. MySQL的事务

    MySQL的事务 1.事务:事务是由一步或者几步数据库操作序列组成的逻辑执行单元,这一系列操作要么全部执行,要么全部放弃执行. 2.事务具备的四个特性(简称为ACID性): (1)原子性(Atomic ...

随机推荐

  1. C++面试常见考点

    这两周参加了3家公司的面试,一家是做嵌入式的外企,一家是做智能家居的初创公司,一家是做网络分析的公司. 通过参加面试,越发的觉得语言只是基础,虽然都是计算机领域,但是不同的业务肯能用到的技术不同,所以 ...

  2. ios UITableView背景图片设置

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPa ...

  3. 解决Detected problems with API compatibility...

    如果是10.3.0那么targetsdk改28.

  4. 30行python让图灵机器人和茉莉机器人无止尽的瞎扯蛋

    首先注册申请图灵机器人的API: http://www.tuling123.com/ 查看一下API的格式,很简单: { "key": "APIKEY", &q ...

  5. Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC 配置校验器

    Spring4新特性——泛型限定式依赖注入 Spring4新特性——核心容器的其他改进 Spring4新特性——Web开发的增强 Spring4新特性——集成Bean Validation 1.1(J ...

  6. html 调用ocx控件

    !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/x ...

  7. 2.19 cookie相关操作

    2.19 cookie相关操作 前言虽然cookie相关操作在平常ui自动化中用得少,偶尔也会用到,比如登录有图形验证码,可以通过绕过验证码方式,添加cookie方法登录.登录后换账号登录时候,也可作 ...

  8. java ip number to string

    package com.awkj; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownH ...

  9. 查看Windows端口及端口关闭方法

    一.查看已开放的端口: 1.借助系统自带MS-DOS命令查看开放的端口(Win2000/XP/server2003) 在开始-运行-输入cmd,打入netstat -an(注意-前有个小空格),在IP ...

  10. 密码安全存储——PBKDF2、bcrypt、scrypt

    密码用单向哈希存储保证了数据库被脱后用户密码的安全. 由于彩虹表这种攻击方式的存在,一般认为md5,SHA1等单向算法的安全性是不够的.那如何选择合适的加密算法? 下面介绍业界几种高强度单向哈希算法, ...