当mysql开启binlog日志时,会存在一个内部XA的问题:事务在存储引擎层redo log的写入和binlog的写入一致性问题。

mysql通过两阶段提交很好的解决了redo log和binlog一致性问题:

第一阶段:innodb prepare, 持有prepare_commit_mutex,redo log持久化到磁盘(flush/sync redolog),并将回滚段设置为prepare状态。

第二阶段:分为两步。

  a. flush/sync binlog

  b. commit(写入commit标记,释放prepare_commit_mutex,并释放回滚段)

事务的崩溃恢复过程如下:

1. 事务恢复时,扫描最后一个binlog,提取出其中的xid

2. xid也会写到redo中,重做检查点后的所有事务,包括未提交的事务和已回滚的事务,读取事务的undo段信息,搜集处于prepare阶段的事务链表,将redo中prepared状态的xid与binlog中的xid做比较,如果在binlog中存在,则提交;否则回滚。

为什么只扫描最后一个binlog?

因为binlog rotate的binlog文件中对应的事务一定是已经提交的

Group Commit:

上面的整个过程,通过持有 prepare_commit_mutex来保证redolog的写入和binlog的写入完全一致,会导致group commit无法生效。

在mysql56中,同时支持了redolog 和 binlog的组提交,其提交流程如下:

第一阶段: innodb prepare(Redo Group Commit)

在innodb中,每条redolog都有自己的LSN,这是一个单调递增的值。每个事务的更新操作都会包含一条或者多条redo log, 各个事务在将redo log写入 log_sys_buffer(通过log_sys mutex保护)时,都会获取当前事务最大的LSN。那么假设三个事务 tx1, tx2, tx3的最大LSN分别为 LSN1 < LSN2 < LSN3时,他们同时进行提交,如果tx3获取到了 log_mutex, 那么他会将小于LSN3之前的redo log一起落盘,这样 tx1, tx2不用再次请求磁盘io。同时,如果存在tx0的LSN0 < LSN3,LSN0也会落盘,即使tx0还没有提交。

1. 获取 log mutex

2. 如果 flushed_to_disk_lsn >= lsn, 表示日志已经被刷盘,跳转 5

3. 如果 current_flush_lsn >= lsn, 表示日志正在刷盘中,跳转 5 后进入等待状态

4. 将小于 lsn 的日志刷盘 (flush and sync)

5. 退出 log_mutex

第二阶段: Binlog Group Commit的基本思想是引入队列机制,保证 innodb commit 的顺序与 binlog落盘的顺序一致,并将事务分组,组内的 binlog刷盘动作交给一个事务进行,实现组提交的目的。队列中的第一个事务称为 leader, 其他事务称为 follower。所有的事情交给 leader 去做。: flush stage, sync stage, commit stage

Flush Stage:

将每个事务的 binlog 写入内存

1. 持有 Lock_log mutex [leader持有,follwer等待]

2. 获取队列中的一组 binlog(队列中的所有事务)

3. 将 binlog buffer 到 I/O cache

4. 通知 dump线程 dump binlog [sync_binlog != 1]

Sync Stage:

将内存中的二进制日志刷新到磁盘, 若队列中有多个事务,那么仅一次 fsync 操作就完成了二进制日志的写入,这就是 BLGC。

1. 释放 Lock_log mutex, 持有 Lock_sync mutex[leader持有,follower等待]

2. 将一组 binlog 落盘(sync操作,最耗时,假设 sync_binlog 为 1)

3. 通知 dump线程 dump binlog [sync_binlog = 1]

Commit Stage:

leader根据顺序调用存储引擎层的提交

1. 释放 Lock_sync mutex, 持有 Lock_commit mutex[ leader持有,follower等待]

2. 遍历队列中的事务,逐一进行 innodb commit.

3. 释放 Lock_commit mutex

4. 唤醒队列中等待的线程。

Redo Group Commit优化

每个事务提交时,都会触发一次redo flush/sync动作,由于磁盘读写比较慢,因此很影响系统的吞吐量。

mysql57中,做了针对redo group commit的优化。将 redo log的write/sync延迟到了binlog group commit的 flush stage之后,sync binlog之前。

通过延迟写redo log的方式,显式的为redo log做了一次组写入,并减少了(redo log) log_sys->mutex的竞争。

第一阶段:Innodb Prepare

1. 记录当前的LSN到thd中

第二阶段:Binlog Group Commit

1. 进入Binlog Group Commit的flush阶段;同时,leader搜索队列,算出thd中最大的LSN

2. 将innodb的redo log flush/sync到指定LSN

3. sync binlog

4. commit

参考

https://blog.csdn.net/weixin_38597669/article/details/104096684

https://blog.csdn.net/zhang123456456/article/details/83857127

mysql组提交的更多相关文章

  1. MySQL 组提交(group commit)

    目录 前言 改进 原理 实现 参数 注意 前言 操作系统使用页面缓存来填补内存和磁盘访问的差距 对磁盘文件的写入会先写入道页面缓存中 由操作系统来决定何时将修改过的脏页刷新到磁盘 确保修改已经持久化到 ...

  2. MySQL组提交(group commit)

    MySQL组提交(group commit) 前提: 以下讨论的前提 是设置MySQL的crash safe相关参数为双1: sync_binlog=1 innodb_flush_log_at_trx ...

  3. mysql复制那点事(2)-binlog组提交源码分析和实现

    mysql复制那点事(2)-binlog组提交源码分析和实现 [TOC] 0. 参考文献 序号 文献 1 MySQL 5.7 MTS源码分析 2 MySQL 组提交 3 MySQL Redo/Binl ...

  4. MySQL binlog 组提交与 XA(两阶段提交)

    1. XA-2PC (two phase commit, 两阶段提交 ) XA是由X/Open组织提出的分布式事务的规范(X代表transaction; A代表accordant?).XA规范主要定义 ...

  5. MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】

    概念: XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口.XA为了实现分布 ...

  6. mysql 5.6 binlog组提交

    mysql 5.6 binlog组提交实现原理 http://blog.itpub.net/15480802/viewspace-1411356 Redo组提交 Redo提交流程大致如下 lock l ...

  7. mysql并发复制系列 一:binlog组提交

    http://blog.itpub.net/28218939/viewspace-1975809/ 作者:沃趣科技MySQL数据库工程师  麻鹏飞 MySQL  Binary log在MySQL 5. ...

  8. MySQL崩溃恢复与组提交

      Ⅰ.binlog与redo的一致性(原子) 由内部分布式事务保证 我们先来了解下,当一个commit敲下后,内部会发生什么? 步骤 操作 step1 InnoDB做prepare redo log ...

  9. mysql 5.6 binlog组提交实现原理(转载)

    http://blog.itpub.net/15480802/viewspace-1411356/ Redo组提交 Redo提交流程大致如下 lock log->mutex write redo ...

随机推荐

  1. Docker——run指令中-it与-d的关系

    建立相关的测试容器 #1.只有-d [root@iZwz908j8pbqd86doyrez5Z test]# docker run -d -p 8081:8080 tomcat:9.0 #2.只有-i ...

  2. Circle Linux镜像在阿里云镜像站首发上线

    镜像下载.域名解析.时间同步请点击阿里云开源镜像站 Circle Linux简介 Circle Linux 社区是一个开源.共创的 Linux 社区,将通过完全开放.包容的社区形式与全球开发者共同构建 ...

  3. 如何用系统命令sc修改系统服务

    系统服务是系统的一项重要组成部分,sc命令在特定权限下,可以实现对指定服务的启动项.配置文件及状态进行修改,位置在c:\windows\system32\目录下面,下面就和大家分享一下如何用系统命令s ...

  4. Windows&Linux文件传输方式总结

    在渗透过程中,通常会需要向目标主机传送一些文件,来达到权限提升.权限维持等目的,本篇文章主要介绍一些windows和Linux下常用的文件传输方式. Windows 利用FTP协议上传 在本地或者VP ...

  5. dfs:x+y=z

    #include <iostream.h> int a[100]; static int stat=0; void dfs(int n) { if(n==3) { if(a[0]+a[1] ...

  6. BeanFactory – BeanFactory 实现举例?

    Bean 工厂是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从正真的应用代码中分离. 最常用的BeanFactory 实现是XmlBeanFactory 类.

  7. vue 初识(基础语法与数据驱动模型)

    1.es6的语法 let 特点: 1.局部作用域 2.不会存在变量提升 3.变量不能重复声明 const 特点: 1.局部作用域 2.不会存在变量提升 3.不能重复声明,只声明常量 不可变的量 模板字 ...

  8. ACM - 动态规划 - UVA 1347 Tour

    UVA 1347 Tour 题解 题目大意:有 \(n\) 个点,给出点的 \(x\).\(y\) 坐标.找出一条经过所有点一次的回路,从最左边的点出发,严格向右走,到达最右点再严格向左,回到最左点. ...

  9. ARM指令集详解--汇编

    1.       汇编 1.1.    通用寄存器 通用寄存器 37个寄存器,31个通用寄存器,6个状态寄存器,R13堆栈指针sp,R14返回指针,R15为PC指针, cpsr_c代表的是这32位中的 ...

  10. 为什么局部内部类访问外边的局部变量必须为final

    6.局部内部类访问外边的局部变量时,此变量必须为final类型 马克-to-win:由于技术方面的限制,java的设计者们做出如下语法规定:局部内部类访问外边的局部变量时,此变量必须为final类型, ...