若事务为非只读事务,则每次事务提交时需要进行一次 fsync操作,以此保证重做日志都已经写入磁盘。当数据库发生宕机时,可以通过重做日志进行恢复。虽然固态硬盘的出现提高了磁盘的性能,然而磁盘的fsync性能是有限的。为了提高磁盘 fsync的效率,当前数据库都提供了 group commit的功能,即一次 fsync可以刷新确保多个事务日志被写入文件。对于 InnoDB存储引擎来说,事务提交时会进行两个阶段的操作:

  1. 修改内存中事务对应的信息,并且将日志写入重做日志缓冲
  2. 调用 fsync将确保日志都从重做日志缓冲写入磁盘。

步骤2)相对步骤1)是一个较慢的过程,这是因为存储引擎需要与磁盘打交道。但当有事务进行这个过程时,其他事务可以进行步骤1)的操作,正在提交的事物完成提交操作后,再次进行步骤2)时,可以将多个事务的重做日志通过一次fsync刷新到磁盘,这样就大大地减少了磁盘的压力,从而提高了数据库的整体性能。对于写入或更新较为频繁的操作, group commit的效果尤为明显。
然而在 InnoDB1.2版本之前,在开启二进制日志后, InnodB存储引擎的 group commit功能会失效,从而导致性能的下降。并且在线环境多使用 replication环境,因此二进制日志的选项基本都为开启状态,因此这个问题尤为显著。
导致这个问题的原因是在开启二进制日志后,为了保证存储引擎层中的事务和二进制日志的一致性,二者之间使用了两阶段事务,其步骤如下:

  1. 当事务提交时 InnoDB存储引擎进行 Prepare操作
  2. MySQL数据库上层写入二进制日志
  3. InnoDB存储引擎层将日志写入重做日志文件。
  • a)修改内存中事务对应的信息,并且将日志写人重做日志缓冲。
  • b)调用 fsync将确保日志都从重做日志缓冲写入磁盘。

一旦步骤2)中的操作完成,就确保了事务的提交,即使在执行步骤3)时数据库发生了宕机。此外需要注意的是,每个步骤都需要进行一次 fsync操作才能保证上下两层数据的一致性。步骤2)的 fsync由参数sync_binlog控制,步骤3)的 fsync由参数innodb_flush_log_at_trx_commit控制。因此上述整个过程如图7-18所示。

为了保证 MySQL数据库上层二进制日志的写入顺序和 InnoDB层的事务提交顺序一致, MySQL数据库内部使用了 prepare_commit_mutex这个锁。但是在启用这个锁之后,步骤3)中的步骤a)步不可以在其他事务执行步骤b)时进行,从而导致了 group commit失效。
然而,为什么需要保证 MySQL数据库上层二进制日志的写入顺序和 InnoDB层的事务提交顺序一致呢?这时因为备份及恢复的需要,例如通过工具 xtrabackup或者ibbackup进行备份,并用来建立 replication,如图7-19所示。
可以看到若通过在线备份进行数据库恢复来重新建立 replication,事务T1的数据会产生丢失。因为在 InnoDB存储引擎层会检测事务T3在上下两层都完成了提交,不需要再进行恢复。因此通过锁 prepare_commit_mutex以串行的方式来保证顺序性,然而这会使 group commit无法生效,如图7-20所示。

这个问题最早在2010年的 MySQL数据库大会中提出, Facebook MySQL技术组,Percona公司都提出过解决方案。最后由MariaDB数据库的开发人员 Kristian Nielsen完成了最终的“完美”解决方案。在这种情况下,不但 MySQL数据库上层的二进制日志写入是 group commit的, InnoDB存储引擎层也是 group commit的。此外还移除了原先的锁 prepare commit mutex,从而大大提高了数据库的整体性。 MySQL5.6采用了类似的实现方式,并将其称为 Binary Log Group Commit(BLGC)。
MySQL5.6BLGC的实现方式是将事务提交的过程分为几个步骤来完成,如图7-21所示。

在 MySQL数据库上层进行提交时首先按顺序将其放入一个队列中,队列中的第一个事务称为 leader,其他事务称为 follower, leader控制着 follower的行为。BLGC的步骤分为以下三个阶段:

  1. Flush阶段,将每个事务的二进制日志写入内存中。
  2. Sync阶段,将内存中的二进制日志刷新到磁盘,若队列中有多个事务,那么仅次fsync操作就完成了二进制日志的写入,这就是BLGC。
  3. Commit阶段, leader根据顺序调用存储引擎层事务的提交, InnoDB存储引擎本就支持 group commit,因此修复了原先由于锁 prepare_commit_mutex导致 group commit失效的问题。

当有一组事务在进行 Commit阶段时,其他新事物可以进行 Flush阶段,从而使group commit不断生效。当然 group commit的效果由队列中事务的数量决定,若每次队列中仅有一个事务,那么可能效果和之前差不多,甚至会更差。但当提交的事务越多时, group commit的效果越明显,数据库性能的提升也就越大。
参数 binlog_max_flush_queue_time用来控制 Flush阶段中等待的时间,即使之前的一组事务完成提交,当前一组的事务也不马上进入Sync阶段,而是至少需要等待一段寸间。这样做的好处是 group commit的事务数量更多,然而这也可能会导致事务的响应时间变慢。该参数的默认值为0,且推荐设置依然为0。除非用户的 MySQL数据库系统中有着大量的连接(如100个连接),并且不断地在进行事务的写入或更新操作。

【MySQL技术内幕】49-事务的实现之group commit相关推荐

  1. 读书笔记之MySQL技术内幕

    前言 本文内容基本摘抄自<MySQL技术内幕 InnoDB存储引擎>,以供复习之用,没有多少参考价值.想要更详细了解请参考原书. 第一章.MySQL体系结构和存储引擎 数据库是物理操作系统 ...

  2. Mysql技术内幕InnoDB存储引擎——InnoDB存储引擎

    特此申明: 前段时间找工作所以看了<Mysql技术内幕InnoDB存储引擎>,整理的时候除了参考网上已有的笔记贴,加上自己整合的,可能和别人有雷同之处.不过无所谓啦,写出来自己看看,需要的 ...

  3. MySQL技术内幕-InnoDB存储引擎第2版-学习笔记-01

    MySQL技术内幕-InnoDB存储引擎第2版-学习笔记-01 1. MySQL体系结构和存储引擎 1.1 定义数据库和实例 数据库database: 物理操作系统文件或其他形式文件类型的集合. 当使 ...

  4. MySQL技术内幕-InnoDB存储引擎第2版-学习笔记-02

    MySQL技术内幕-InnoDB存储引擎第2版-学习笔记-02 6. 锁 ​ 人们认为行级锁总会增加开销.实际上,只有当实现本身会增加开销时,行级锁才会增加开销.InnoDB 存储引擎不需要锁升级,因 ...

  5. MySQL技术内幕 InnoDB存储引擎:锁问题(脏读、不可重复读)

    1.脏读 在理解脏读(Dirty Read)之前,需要理解脏数据的概念.但是脏数据和之前所介绍的脏页完全是两种不同的概念.脏页指的是在缓冲池中已经被修改的页,但是还没有刷新到磁盘中,即数据库实例内存中 ...

  6. MySQL必知必会教程:深入理解MySQL技术内幕

    2019独角兽企业重金招聘Python工程师标准>>> MySQL必知必会教程:深入理解MySQL技术内幕 作为最流行的开源数据库软件之一,MySQL数据库软件已经是广为人知了.当前 ...

  7. mysql技术内幕sampdb_MySQL技术内幕汇总

    MySql技术内幕之MySQL入门(1) 检查系统中是否已经安装了MySQL sudo netstat -tap | grep mysql 若没有显示已安装结果,则没有安装.否则表示已经安装. sud ...

  8. mysql技术内幕sampdb_MySql技术内幕之MySQL入门(1)

    MySql技术内幕之MySQL入门(1) 安装 检查系统中是否已经安装了MySQL sudo netstat -tap | grep mysql 若没有显示已安装结果,则没有安装.否则表示已经安装. ...

  9. Mysql技术内幕innodb引擎笔记

    第2章 InnoDB存储引擎 2.3 InnoDB体系架构 InnoDB存储引擎有多个内存块,可以认为这些内存块组成了一个大的内存池,负责如下工作: 维护所有进程/线程需要访问的多个内部数据结构. 缓 ...

最新文章

  1. swift - if let Optional 语法
  2. php如何传递字符串,如何将PHP字符串传递给Javascript函数调用?
  3. leetcood学习笔记-111-二叉树的最小深度
  4. .NET Core 使用Topshelf方式创建Windows服务
  5. 数组实例的copyWithin()方法
  6. C++中类成员函数作为多线程的入口
  7. 数据字典模块设计_使用正则表达式采集整站小说数据小说精品屋爬虫模块的设计与实现...
  8. 基于C#实现的简易绘图工具设计
  9. cocos2dx 圆盘抽奖_Cocos2D-X转盘游戏制作教程:博彩大转盘
  10. 400款营销策划PPT模板免费下载
  11. CSS解决图片过大撑破DIV的方法
  12. SMB CIFS DOMIAN
  13. matlab实现简单清浊音检测
  14. airflow使用macros
  15. 某喷码机品牌U盘存储的配置文件简记
  16. Uniforms(uniform变量)
  17. 用JavaWeb写验证码
  18. 网站可访问性:ARIA入门
  19. 简易方法提高手机3G上网速度(2G转3G)
  20. 解决Keil5软件MDK版本和C51共同使用问题

热门文章

  1. 学生成绩查询系统(Java实现),你第一个Java小项目
  2. 自考计算机数据结构导论,自考数据结构导论……
  3. 0.1+0.2不等于0.3,微信小程序云开发如何解决JavaScript小数计算精度失准的问题
  4. 面向对象语言(JAVA)——工具类(Collections(操作集合)代码实现理解)
  5. HTML调用百度地图API,实现地图标注位置
  6. 硅谷课堂 06_整合腾讯云对象存储和课程分类管理
  7. LiveUpdate(自动更新)经验
  8. Maya 凹凸贴图与置换贴图
  9. win10默认安装路径修改_解放C盘!2种方法教你修改默认安装目录!
  10. 超详细!apk安装包快速反编译,多种反编译及失败的解决方案(包含classes.dex的反编译,新增加快速反编译)