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

http://blog.csdn.net/woqutechteam/article/details/51178803

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

转载于:https://www.cnblogs.com/devilwind/p/8058248.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/415075.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工作188:表单校验规则

1绑定rules <el-dialog title"新建账号" :visible.sync"dialogFormVisible" close"close"><!--1.name--><el-form ref"form" :rules"rules" :model"form" size"medium" :label-width&q…

学习knex过程中好的参考资料整理

记录本人制作博客系统和学习knex找的相关资料链接&#xff1a; 1、博客系统 https://github.com/huoguozhang/my-blog/tree/master/models 2、与typescript结合&#xff0c;TypeScript Express Objection.js Knex.js MySQL https://github.com/corocn/ts-server/tree/61c…

js-----Date==字符串

<html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"> <title>js将当前时间转换为字符串日期</title> <script type"text/javascript" src"jquery-1.11.1.min.js"&…

Android Studio 项目断开SVN连接

Android Studio 断开 SVN 1.打开项目所在的文件夹&#xff0c;找到.idea文件夹 2.打开.idea文件夹&#xff0c;找到vcs.xml文件并打开 3.把vcs对应的值删掉&#xff0c;vcs“” 4.重要的来了&#xff0c;删除项目中关联svn时创建的svn隐藏文件。 在查看中设置显示隐藏的文…

工作189:配置表头即可

columns: [{type: "selection", width: "50"},{prop: "id", label: "ID", width: "60", sortable: true},{prop: "name", label: "账号名称", width: "100", sortable: true},{prop: "d…

什么是eager loading

在做objectionknexmysql技术栈开发过程中&#xff0c;进行关联数据查询时&#xff0c;遇到这个关键词eager loading,现在进行解释一下&#xff1a; eager loading其实就是preloading的意思。就是尽可能把后面需要的数据&#xff0c;通过最少的sql语句一起查询出来&#xff0c;从…

Robotium_断言方法assert、is、search

下面的这些方法都主要用来判断测试结果是否与预期结果相符&#xff0c;一般把is和search方法放在assert里面判断。assert最常用的还是assertThat方法&#xff0c;是Junit的判断&#xff0c;这里就不多说了。断言方法assert&#xff08;robotium特有的断言方式&#xff0c;实际项…

工作190:页面数据不显示

账户详情里面没有返回对应的字段 所以页面不显示

mysql两张主表person event加上第三张关联表

有两个对象&#xff0c;个人person、活动event。每个person可以参加多个event&#xff0c;每个event可以由多person参加。数据库表格如下&#xff1a; event - id [int (4),primary] - name [varchar (30)] - …person - id [int (4),primary] - name [varcha…

List的五种去重方式

一、String去重&#xff1a; //set集合去重&#xff0c;不改变原有的顺序public static void pastLeep1(List<String> list){System.out.println("list [" list.toString() "]");List<String> listNewnew ArrayList<>();Set setne…

python Shapely OSError: Could not find lib c or load any of its variants []

mac 升级过后&#xff0c;python项目运行报错python Shapely OSError: Could not find lib c or load any of its variants []。 在github上找到解决办法没记录如下&#xff1a; To recap, I removed anything dealing with conda that depends on geos: conda remove geos, s…

工作192:vue项目如何刷新当前页面

1.场景 在处理列表时&#xff0c;常常有删除一条数据或者新增数据之后需要重新刷新当前页面的需求。 2.遇到的问题 1. 用vue-router重新路由到当前页面&#xff0c;页面是不进行刷新的 2.采用window.reload()&#xff0c;或者router.go(0)刷新时&#xff0c;整个浏览器进行…

python保存文件,如果目录不存在,则创建

对于python 3.2 以上版本使用 import osfilename "/user/project/demo.txt" os.makedirs(os.path.dirname(filename), exist_okTrue) with open(filename, "w") as f:f.write("FOOBAR")

CentOS挂Windows的NFS备忘

Windows NFS 安装和配置 注&#xff1a;需要将名称为“所有计算机”的访问类型改为“无访问权限”&#xff0c;再将可访问IP的访问类型改为“读写”&#xff0c;并勾选“允许根目录访问” &#xff0c;如WINDOWS有防火墙开放“2049”端口 CentOS需要开启两个服务&#xff1a; y…

NotificationManager: notifyAsUser: tag=null, id=6, user=UserHandle{0}

Android studio 使用 targetSdkVersion 28 在Android系统大于等于8.0的时候&#xff0c;通知不显示bug解决方法&#xff1a; 1、修改appcompat版本&#xff0c;如果是小于v27 改为 implementation com.android.support:appcompat-v7:27.1.1 2、添加依赖 compile com.git…

工作193:vue.runtime.esm.js?2b0e:619 [Vue warn]: <transition-group> children must be keyed: <ElTag>

标题[Vue warn]: children must be keyed: 今天学习了VUE的列表排序过渡 碰见报错 报错之前代码为&#xff1a; <transition-group name"flip-list" tag"div"><van-cell v-for"(item,i) in list" v-bind:key"item.id">{…

prettier 配置参数说明

有必要使用prettier进行代码格式化。 1、常用的配置说明如下&#xff1a; {// 使能每一种语言默认格式化规则"[html]": {"editor.defaultFormatter": "esbenp.prettier-vscode"},"[css]": {"editor.defaultFormatter": &qu…

Oracle之例外(异常)

/* 例外 其实就是异常 处理发生的异常 java try{}catch(OutofBoundIndexException){}catch(Exception e){} 数据库对异常的处理 exception when 异常类型 then 处理语句 数据库异常分类 运行时异常 编…

Android2.2查看svn历史提交记录

一开始时是没有显示历史提交记录的&#xff0c;方法很简单 VCS--Subversion--ShowHistory,之后在下面的Version control就会显示“History-项目名”这个栏目&#xff0c;在这个栏目下面就可以查看提交的历史记录了 方法2&#xff1a; 对文件夹点右键&#xff0c;点击TortoiseS…