上一篇文章我们介绍了在关闭binlog的情况下,事务提交的大概流程。之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称之为内部xa事务(Distributed Transactions),与之对应的还有一个外部xa事务。

这里所谓的两阶段提交分别是prepare阶段和commit阶段。

内部xa事务主要是mysql内部为了保证binlog与redo log之间数据的一致性而存在的,这也是由其架构决定的(binlog在mysql层,而redo log 在存储引擎层);

外部xa事务则是指支持多实例分布式事务,这个才算是真正的分布式事务。

既然是xa事务,必然涉及到两阶段提交,对于内部xa而言,同样存在着提交的两个阶段。

下文会结合源码详细解读内部xa的两阶段提交过程,以及各种情况下,mysqld crash后,mysql如何恢复来保证事务的一致性。

测试环境

OS:WIN7

ENGINE:

DB:

配置文件参数:

log-bin=D:\mysql\log\5-6-21\mysql-bin

binlog_format=ROW

set autocommit=0;

innodb_support_xa=1

sync_binlog=1;

innodb_flush_log_at_trx_commit=1;

【innodb_flush_log_at_trx_commit=1,sync_binlog=1

不同的模式区别在于,写文件调用write和落盘fsync调用的频率不同,所导致的后果是mysqld 或 os crash后,不严格的设置可能会丢失事务的更新。

双一模式是最严格的模式,这种设置情况下,单机在任何情况下不会丢失事务更新。】

测试条件

set autocommit=0;
-- ----------------------------

-- Table structure for `user`

-- ----------------------------

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (

`id` int(20) NOT NULL,

`account` varchar(20) NOT NULL,

`name` varchar(20) NOT NULL,

PRIMARY KEY (`id`),

KEY `id` (`id`) USING BTREE,

KEY `name` (`name`) USING BTREE

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

测试语句

insert into user values(1, 'sanzhang', '张三');
commit;

prepare阶段:

1.设置undo state=TRX_UNDO_PREPARED; //trx_undo_set_state_at_prepare调用

2.刷事务更新产生的redo日志;【步骤1产生的redo日志也会刷入】

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阶段:

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调用

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 crash,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

binlog日志文件是为了解决MySQL主从复制功能而引入的一份新日志文件,它包含了引发数据变更的事件日志集合。

从库请求主库发送 binlog 并通过日志事件还原数据写入从库,所以从库的数据来源为 binlog。

这样 MySQL 主库只需做到 binlog 与本地数据一致就可以保证主从库数据一致(暂且忽略网络传输引发的主从不一致)。

参考

1、《高性能MySQL》

2、mysql 事务提交过程

MySQL事务提交过程(二)的更多相关文章

  1. MySQL事务提交过程

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

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

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

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

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

  4. mysql 事务提交过程

     打开binlog选项后,执行事务提交命令时,就会进入两阶段提交模式.两阶段提交分为prepare阶段和commit两个阶段.流程如下 :这里面涉及到两个重要的参数:innodb_flush_log_ ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. python安装提示No module named setuptools,wget提示ERROR 403: SSL is required

    在下载安装一个python工具时提示报错No module named setuptools [root@kermit supervisor-3.3.0]$ sudo python setup.py ...

  2. java中package指什么

    为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间,类似C#的 namespace的作用,防止名字相同的类产生冲突. Java中的一个package(包)就是一个类库单元,包内包含有一组 ...

  3. rsyslog的安装、使用、详解

    操作系统:CentOS release 6.7 download yum repo file:rsyslogall.repo [rsyslog-v8-stable] name=Adiscon Rsys ...

  4. 尚硅谷《全套Java、Android、HTML5前端视频》

    尚硅谷<全套Java.Android.HTML5前端视频> (百万谷粉推荐:史上最牛.最适合自学的全套视频.资料及源码) [尚硅谷官网资料导航] 谷粒学院在线学习:http://www.g ...

  5. Confluence 6 用户目录图例 - 连接 Jira

    上面的图:Confluence 连接到 JIRA 为用户管理. https://www.cwiki.us/display/CONFLUENCEWIKI/Diagrams+of+Possible+Con ...

  6. Java语法基础常见疑惑解答8,16,17,21图片补充

    8. 16. 17. 21

  7. Android源码分析二 硬件抽象层(HAL)

    一 什么是HAL HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现.借助 HAL,您可以顺利实现相关功能,而不会影响或更改更高级别的系统.HAL 实现会 ...

  8. redis持久化之AOF

    一:Redis的AOF是什么? 以日志的形式来记录每个写操作(读操作不记录),将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构 ...

  9. cf478d 线性dp好题

    /* 给定r个红块,g个绿块,按要求堆放 问当堆放成最大高度时,有多少种可能的堆放方式 排列要求:1.第i行放i块 2.每行同色 首先当然要确定能够放置几行 设红块有r个,绿块有g个,那么放置h行需要 ...

  10. Nginx详解二十三:Nginx深度学习篇之Nginx+Lua开发环境搭建

    Nginx+Lua开发环境 1.下载LuaJIT解释器wget http://luajit.org/download/LuaJIT-2.0.2.tar.gztar -zxvf LuaJIT-2.0.2 ...