http://blog.itpub.net/28218939/viewspace-1975809/

作者:沃趣科技MySQL数据库工程师  麻鹏飞


MySQL  Binary log在MySQL 5.1版本后推出主要用于主备复制的搭建,我们回顾下MySQL 在开启/关闭 Binary Log功能时是如何工作的 。

MySQL没有开启Binary log的情况下:

  • InnoDB存储引擎通过redo和undo日志可以safe crash recovery数据库,当数据crash recovery时,通过redo日志将所有已经在存储引擎内部提交的事务应用redo log恢复,所有已经prepared但是没有committransactions将会应用undo logroll back。然后客户端连接时就能看到已经提交的数据存在数据库内,未提交被回滚地数据需要重新执行。

MySQL开启Binary log 的情况下:

  • 为了保证存储引擎和MySQL数据库上层的二进制日志保持一致(因为备库通过二进制日志重放主库提交的事务,假设主库存储引擎已经提交而二进制日志没有保持一致,则会使备库数据丢失造成主备数据不一致),引入二阶段提交(two phase commit or 2pc)

图1 二阶段提交

MySQL二阶段提交流程:

Storage Engine(InnoDB) transaction prepare阶段:即sql语句已经成功执行并生成redo和undo的内存日志

Binary log日志提提交

      • write()将binary log内存日志数据写入文件系统缓存
      • fsync()将binary log 文件系统缓存日志数据永久写入磁盘

Storage Engine(InnoDB)内部提交

      • commit阶段在存储引擎内提交( innodb_flush_log_at_trx_commit控制)使undo和redo永久写入磁盘

开启Binary log的MySQL在crash recovery时:

  • 当事务在prepare阶段crash,数据库recovery的时候该事务未写入Binary log并且存储引擎未提交,将该事务roll back
  • 当事务在Binary log日志已经fsync()永久写入二进制日志时crash,但是存储引擎未来得及commit,此时MySQL数据库recovery的时候将会从二进制日志的Xid(MySQL数据库内部分布式事务XA)中获取提交的信息重新将该事务重做并commit使存储引擎和二进制日志始终保持一致。

以上提到单个事务的二阶段提交过程,能够保证存储引擎和binary log日志保持一致,但是在并发的情况下怎么保证存储引擎和Binary Log提交的顺序一致?当多个事务并发提交的情况,如果Binary Log和存储引擎顺序不一致会造成什么影响?

 
 图2 InnoDB存储引擎提交的顺序与MySQL上层的二进制日志顺序不同

如上图:事务按照T1T2T3顺序开始执行,将二进制日志(按照T1、T2、T3顺序)写入日志文件系统缓存,调用fsync()进行一次group commit将日志文件永久写入磁盘,但是存储引擎提交的顺序为T2T3T1当T2、T3提交事务之后做了一个On-line的backup程序新建一个slave来做replication,那么事务T1在slave机器restore MySQL数据库的时候发现未在存储引擎内提交,T1事务被roll back,此时主备数据不一致(搭建Slave时,change master to的日志偏移量记录T3在事务位置之后)。

结论:MySQL数据库上层二进制日志的写入顺序和存储引擎InnoDB层的事务提交顺序一致,用于备份及恢复需要,如xtrabackup和innobackpex工具。
      为了解决以上问题,在早期的MySQL版本,通过prepare_commit_mutex 锁保证MySQ数据库上层二进制日志和Innodb存储引擎层的事务提交顺序一致。

 图3 通过prepare_commit_mutex保证存储引擎和二进制日志顺序提交顺序一致

图3可以看出在prepare_commit_mutex,只有当上一个事务commit后释放锁,下一个事务才可以进行prepara操作,并且在每个transaction过程中Binary log没有fsync()的调用。由于内存数据写入磁盘的开销很大,如果频繁fsync()把日志数据永久写入磁盘数据库的性能将会急剧下降。此时MySQL 数据库提供sync_binlog参数来设置多少个binlog日志产生的时候调用一次fsync()把二进制日志刷入磁盘来提高整体性能,该参数的设置作用:

  • sync_binlog=0,二进制日志fsync()的操作基于操作系统。
  • sync_binlog=1,每一个transaction commit都会调用一次fsync(),此时能保证数据最安全但是性能影响较大。
  • sync_binlog=N,当数据库crash的时候至少会丢失N-1个transactions。

图3 所示MySQL开启Binary log时使用prepare_commit_mutex和sync_log保证二进制日志和存储引擎顺序保持一致(通过sync_binlog来控制日志的刷新频率),prepare_commit_mutex的锁机制造成高并发提交事务的时候性能非常差而且二进制日志也无法group commit。

那么如何保证MySQL开启Binary Log日志后使二进制日志写入顺序和存储引擎提交顺序保持一致并且能够进行二进制日志的Group Commit

MySQL 5.6 引入BLGC(Binary Log Group Commit),二进制日志的提交过程分成三个阶段,Flush stage、Sync stage、Commit stage。

那么事务提交过程简化为:

存储引擎(InnoDB) Prepare    ---->    数据库上层(Binary Log)   Flush Stage    ---->    Sync Stage    ---->    调存储引擎(InnoDBCommit stage.

每个stage阶段都有各自的队列,使每个session的事务进行排队。当一个线程注册了一个空队列,该线程就视为该队列的leader,后注册到该队列的线程为follower,leader控制队列中follower的行为。leader同时带领当前队列的所有follower到下一个stage去执行,当遇到下一个stage并非空队列,此时leader可以变成follower到此队列中(注:follower的线程不可能变成leader)

 图4: 二进制日志三阶段提交过程

在 Flush stage:所有已经注册线程都将写入binary log缓存

在Sync stage :binary log缓存的数据将会sync到磁盘,当sync_binlog=1时所有该队列事务的二进制日志缓存永久写入磁盘

在 Commit stage:leader根据顺序调用存储引擎提交事务。

当一组事务在进行Commit阶段时,其他新的事务可以进行Flush阶段,从而使group commit不断生效。那么为了提高group commit中一组队列的事务数量,MySQL用binlog_max_flush_queue_time来控制在Flush stage中的等待时间,让Flush队列在此阶段多等待一些时间来增加这一组事务队列的数量使该队列到Sync阶段可以一次fysn()更多的事务。

MySQL 5.7 Parallel replication实现主备多线程复制基于主库Binary Log Group Commit, 并在Binary log日志中标识同一组事务的last_commited=N和该组事务内所有的事务提交顺序。为了增加一组事务内的事务数量提高备库组提交时的并发量引入了binlog_group_commit_sync_delay=N 和binlog_group_commit_sync_no_delay_count=N (注:binlog_max_flush_queue_time MySQL5.7.9及之后版本不再生效)参数,MySQL等待binlog_group_commit_sync_delay毫秒直到达到binlog_group_commit_sync_no_delay_count事务个数时,将进行一次组提交。

Reference:http://mysqlmusings.blogspot.kr/2012/06/binary-log-group-commit-in-mysql-56.html

mysql并发复制系列 一:binlog组提交的更多相关文章

  1. MySQL并发复制系列一:binlog组提交 (转载)

    http://blog.csdn.net/woqutechteam/article/details/51178803 MySQL  Binary log在MySQL 5.1版本后推出主要用于主备复制的 ...

  2. MySQL并发复制系列三:MySQL和MariaDB实现对比

    http://blog.itpub.net/28218939/viewspace-1975856/ 并发复制(Parallel Replication) 系列三:MySQL 5.7 和MariaDB ...

  3. MySQL并发复制系列二:多线程复制

     http://blog.itpub.net/28218939/viewspace-1975822/ 并发复制(Parallel Replication) 系列二: Enhanced Multi-th ...

  4. MySQL并发复制系列二:多线程复制 2016

    并发复制(Parallel Replication) 系列二: Enhanced Multi-threaded Slaves作者:沃趣科技MySQL数据库工程师  麻鹏飞 首先梳理下传统MySQL/M ...

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

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

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

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

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

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

  8. MySQL binlog 组提交与 XA(两阶段提交)--1

    参考了网上几篇比较靠谱的文章 http://www.linuxidc.com/Linux/2015-11/124942.htm http://blog.csdn.net/woqutechteam/ar ...

  9. mysql 5.6 binlog组提交

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

随机推荐

  1. codeforces 681D Gifts by the List dfs+构造

    题意:给你一个森林,表示其祖先关系(自己也是自己的祖先),每个人有一个礼物(要送给这个人的固定的一个祖先) 让你构造一个序列,使得的对于每个人,这个序列中第一个出现的他的祖先,是他要送礼物的的那个祖先 ...

  2. jquery的each()函数用法

    each()方法能使DOM循环结构简洁,不容易出错.each()函数封装了十分强大的遍历功能,使用也很方便,它可以遍历一维数组.多维数组.DOM, JSON 等等 在javaScript开发过程中使用 ...

  3. OpenGL超级宝典第5版&&GLSL法线变换

    在GLSL中,有一些情况需要把局部坐标系下的向量或点转换到视点坐标系下,如光照计算时,需要把法向转化到视点坐标系.如果是模型上一点p 转化到视点坐标系下,直接(model-view matrix )* ...

  4. CSS基础知识—【结构、层叠、视觉格式化】

    结构和层叠 选择器的优先级顺序: style[内联元素]选择器>Id选择器>类选择器 属性选择器>元素选择器>通配器选择器 重要性:@important 有这个标记的属性值,优 ...

  5. 学习Python编程的11个资源

    用 Python 写代码并不难,事实上,它一直以来都是被声称为最容易学习的编程语言.如果你正打算学习 web 开发,Python 是一个不错的选择,甚至你想学游戏开发也可 以从 Python 开始,因 ...

  6. Hbase 基本命令

    启动Hbase:./start-hbase.sh 进入Hbase shell控制台:./hbase shell   查看所有表 list   查看数据库状态:status   查看数据库版本:vers ...

  7. 【转】并发编程之Operation Queue

    http://blog.xcodev.com/blog/2013/10/28/operation-queue-intro/ 随着移动设备的更新换代,移动设备的性能也不断提高,现在流行的CPU已经进入双 ...

  8. HDU 5724 Chess (sg函数)

    Chess 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5724 Description Alice and Bob are playing a s ...

  9. UVaLive 7359 Sum Kind Of Problem (数学,水题)

    题意:给定一个n,求前 n 个正整数,正奇数,正偶数之和. 析:没什么好说的,用前 n 项和公式即可. 代码如下: #pragma comment(linker, "/STACK:10240 ...

  10. 学习php 韩顺平 数据类型 三元运算,字符串运算类型运算

    数据类型 整型:int 4个字节长度 1个字节8个bit 所以最大的整型数值是2的31次方 第一位是的0,1 表示正负,0表示正数,1表示负数 小数(float)分 精度计算  从左边开始算第一个不为 ...