mysql 5.6 binlog组提交

mysql 5.6 binlog组提交实现原理

http://blog.itpub.net/15480802/viewspace-1411356

 

Redo组提交

Redo提交流程大致如下

lock log->mutex

write redo log buffer to disk

unlock log->mutex

fsync

 

Fsync写磁盘耗时较长且不占用log->mutex,也就是其执行期间其他线程可以write log buffer;

假定一次fsync需要10ms,而写buffer只需要1ms,则fsync执行期间最多可以有10条redo record写入buffer,则下次调用fsync时可一次性写10条记录;

 

 

binlog组提交

Mysql 从 5.0 开始支持2PC,在代码实现时为了保证Binlog中的事务顺序和事务commit顺序一致,放弃了Group Commit。

如果Binlog顺序不一致,那么备库就无法确保和主库有一致的数据。这个问题直到 mysql 5.5 才开始部分修复,到 mysql 5.6 完全修复。

在 mysql 5.5 中,只有当 sync_binlog = 0 时,才能使用 group commit,在 mysql 5.6中都可以进行 group commit。

 

2PC下的事务提交流程

1. Prepare Innodb:

   a) Write prepare record to Innodb's log buffer

   b) Sync log file to disk  -- redo组提交

   c) Take prepare_commit_mutex

2. "Prepare" binary log:

   a) Write transaction to binary log

   b) Sync binary log based on sync_binlog

3. Commit Innodb:

   a) Write commit record to log

   b) Release prepare_commit_mutex

   c) Sync log file to disk

   d) Innodb locks are released

4. "Commit" binary log:

   a) Nothing necessary to do here.

 



 

 

不足

为保证binlog按顺序写,prepare redo阶段获取prepare_commit_mutex,直到sync redo前才释放;一次只能有一个事务可获取该mutex,阻碍了group commit;

另外,一次完整的事务提交需要调用3次fsync,效率很低;

 

改进

1 减少fsync

crash recovery时先查看redo log,找出prepared但没有commited或aborted的事务列表,然后检查binlog,如果binlog记录了该事务,则将其commit否则rollback;

由此可见,事务恢复时取决于binlog是否有记录,因此commit innodb时无须调用立即fsync(此时binlog已写入,就算crash也能保证事务提交);

 

2 细化binlog commit代码,实现组提交

在Oracle MySQL 5.6.15中,binlog group commit模块被重写,这个过程分为3个stage:flush/sync/commit;

 

 

5.6的2PC提交流程如下

1. Ask binary log (i.e. coordinator to prepare

  a) Request to release locks earlier

  b) Prepare Innodb (Callback to (2.a))

2. Prepare Innodb:

  a) Write prepare record to Innodb log buffer

  b) Sync log file to disk

3. Ask binary log (i.e. coordinator) to commit

  a) Lock access to flush stage

  b) Write a set of transactions to the binary log

  c) Unlock access to flush stage

  d) Lock access to sync stage

  e) Flush the binary log to disk

  f) Unlock access to sync stage

  g) Lock access to commit stage

  h) Commit Innodb (Callback to (4.a))

  i) Unlock access to commit stage

4. Commit Innodb

  a) Write a commit record to Innodb log buffer

 

binlog提交被细化为3个处理阶段,每一阶段都有lock保护(此时redo已经调用fsync,事务尚未提交);

 

这3个阶段负责批量读取binlog并调用fsync,而后以同样顺序提交事务(可选);

第一个进入处理阶段的事务担当Leader的角色,剩余的为follower,后者释放所有的latch并等待,直至leader完成commit;

leader获取所有排队等待的事务并处理,进入下一个处理阶段时,如果队列为空则仍是leader,否则降级为follower;

1. Flush Stage

leader会不断读取flush queue直到队列为空或者超时,这样允许处理过程中新加入的事务也能得到及时处理;

leader将排队的事务写入binlog buffer,当队列为空时则进入下一阶段;

超时机制避免了事务长时间等待,

2. Sync Stage

调用fsyc,一次刷新多个事务;

3. Commit Stage

提交事务,保证所有事务提交顺序同写入binlog一致(innodb hot backup); 为了提升性能,也可选择不按次序提交;

 

代码实现

Binlog原本实现了handlerton接口,包括commit()/rollback()等方法,5.6引入新机制

public class MYSQL_BIN_LOG: public TC_LOG

{

  int open_connection(THD* thd);

  int close_connection(THD* thd);

  int commit(THD *thd, bool all);

  int rollback(THD *thd, bool all);

  int savepoint_set(THD* thd, SAVEPOINT *sv);

  int savepoint_release(THD* thd, SAVEPOINT *sv);

  int savepoint_rollback(THD* thd, SAVEPOINT *sv);

};

 

int MYSQL_BIN_LOG::commit(THD *thd, bool all)

{

  /* Call batch_commit(). */

}

 

int MYSQL_BIN_LOG::batch_commit(THD* thd, bool all)

{

--将事务加入flush queue,第一个事务为leader,follower阻塞直至完成commit;

  if (change_stage(thd, Stage_manager::FLUSH_STAGE, thd, NULL, &LOCK_log))

    return finish_commit(thd->commit_error);

 

--将事务写入binlog

  THD *flush_queue= NULL; /* Gets a pointer to the flush_queue */

  error= flush_stage_queue(&wait_queue);

 

  if (change_stage(thd, Stage_manager::SYNC_STAGE, wait_queue, &LOCK_log, &LOCK_sync))

    return finish_commit(thd->commit_error);

 

--依据sync_binlog选项调用fsync,5.5却只能将sync_binlog=0

  THD *sync_queue= NULL; /* Gets a pointer to the sync_queue */

  error= sync_stage_queue(&sync_queue);

 

--根据opt_binlog_order_commits,可以按binlog写入顺序提交事务,也可以让线程调用handlerton->commit各自提交;

  if (opt_binlog_order_commits)

  {

    if (change_stage(thd, Stage_manager::COMMIT_STAGE,

                     final_queue, &LOCK_sync, &LOCK_commit))

      return finish_commit(thd);

    THD *commit_queue= NULL;

 

    error= commit_stage_queue(&commit_queue);

    mysql_mutex_unlock(&LOCK_commit);

    final_queue= commit_queue;

  }

  else

  {

    final_queue= sync_queue;

    mysql_mutex_unlock(&LOCK_sync);

  }

 

--通知follower,要么提交事务(opt_binlog_order_commits=false)要么通知客户端;

  stage_manager.signal_done(final_queue);

 

  return finish_commit(thd);

}

 

参考资料

http://dev.mysql.com/worklog/task/?id=5223

http://mysqlmusings.blogspot.co.uk/2012/06/binary-log-group-commit-in-mysql-56.html?_sm_au_=iDV88W54k66P05L7

 

 


后记:
看到淘宝分享的一篇帖子,在5.6的基础上还有优化的空间,要保证一个事务能成功恢复,只需要保证在binlog commit前将对应事务的redo entry写入磁盘即可,则redo commit/sync完全可以从redo prepare后移到binlog prepare,将其放于flush stage和commit stage之间,将原本N次的log_sys->mutex获取次数降为1次,fsync也变为1次;
问题
每个事务都要保证其Prepare的事务被write/fsync到redo log文件。尽管某个事务可能会帮助其他事务完成redo 写入,但这种行为是随机的,并且依然会产生明显的log_sys->mutex开销。
优化
从XA恢复的逻辑我们可以知道,只要保证InnoDB Prepare的redo日志在写Binlog前完成write/sync即可。因此我们对Group Commit的第一个stage的逻辑做了些许修改,大概描述如下:
Step1. InnoDB Prepare,记录当前的LSN到thd中; 
注:原本此阶段需要获取log->mutex进行的写文件取消,延迟到下一阶段;在原有fsync组提交的基础上实现写文件组提交。
Step2. 进入Group Commit的flush stage;Leader搜集队列,同时算出队列中最大的LSN。
Step3. 将InnoDB的redo log write/fsync到指定的LSN 
Step4. 写Binlog并进行随后的工作(sync Binlog, InnoDB commit , etc)
通过延迟写redo log的方式,显式的为redo log做了一次组写入,并减少了log_sys->mutex的竞争。
目前官方MySQL已经根据我们report的bug#73202锁提供的思路,对5.7.6的代码进行了优化,对应的Release Note如下:
When using InnoDB with binary logging enabled, concurrent transactions written in the InnoDB redo log are now grouped together before synchronizing to disk when innodb_flush_log_at_trx_commit is set to 1, which reduces the amount of synchronization operations. This can lead to improved performance.
简单测试了下,使用sysbench, update_non_index.lua, 100张表,每张10w行记录,innodb_flush_log_at_trx_commit=2, sync_binlog=1000,关闭Gtid
并发线程        原生                  修改后
32             25600                27000
64             30000                35000
128            33000                39000
256            29800                38000

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

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

相关文章

python基础(正则表达式)

http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html 转载于:https://www.cnblogs.com/wanderingzj/p/5253325.html

LinuxShell脚本之利用rsync+ssh实现Linux文件系统远程备份

功能介绍:该脚本用于定期(结合crontab一起使用)将本地目录通过rsyncssh传输到远程服务器,每次执行都生成一个带有以时间命名的目录,并且当前最新版本的数据链接到一个名字叫current的符号链接上,便于查找和…

张正友相机标定Opencv实现以及标定流程标定结果评价图像矫正流程解析(附标定程序和棋盘图)

from:https://blog.csdn.net/dcrmg/article/details/52939318使用Opencv实现张正友法相机标定之前,有几个问题事先要确认一下,那就是相机为什么需要标定,标定需要的输入和输出分别是哪些?相机标定的目的:获…

软件测试技术 homework2

Code 1 1.fault是迭代的条件应该是 i > 0 而不是 i > 0 2.当测试用例是 [3,2,1],1 时。 3.当测试用例是 [2,3,4],1 。 4.当测试用例是 [2],1 。 Code 2 1.fault是应该逆序迭代,正确为for(int i x.length-1;i>0;i--) 2.当测试用例是[0,1&#x…

header的安全配置指南

0x00 背景 在统计了Alexa top 100万网站的header安全分析之后(2012年11月 - 2013年3月 - 2013年11月),我们发现其实如何正确的设置一个header并不是一件容易的事情。尽管有数不胜数的网站会使用大量有关安全方面的header,但 并没有…

opencv双目视觉标定、匹配和测量 (附代码)

from:https://blog.csdn.net/bcj296050240/article/details/52778741双目视觉原理方面参照《学习Opencv》和大牛博客 http://blog.csdn.net/chenyusiyuan/article/details/5970799中16-19系列博客。本文主要记录我自己在双目视觉标定,立体匹配&#xff0…

dom内容区域的滚动overflow,scroll

去掉手机上点击点中的默认高亮效果 -webkit-tap-highlight-color: rgba(0,0,0,0); ios手动启动一下监听touch事件以响应css伪类: document.addEventListener("touchstart", function(){}, true) 传统 pc 端中,子容器高度超出父容器高度,通常使…

工业相机的选择方法

信号  工业相机的信号类型有模拟信号和数字信号两种。模拟相机必须有图像采集卡,标准的模拟相机分辨率很低,采集到的是模拟信号,经数字采集卡转换为数字信号进行传输存储。工业数字相机采集到的是数字信号,数字信号不受电噪声影…

atitit.短信 验证码  破解  v3 p34  识别 绕过 系统方案规划----业务相关方案 手机验证码  .doc...

atitit.短信 验证码 破解 v3 p34 识别 绕过 系统方案规划----业务相关方案 手机验证码 .doc 1. 手机短信验证码 vs 图片验证码 安全性(破解成本)确实要高一些1 1.1. 破解基本原则有两种,一种是绕过验证码。一种是拦截1 2. 手机 短信 验证…

SpringMvc整合Quartz实现定时任务项目源码

项目中一直使用Quartz做定时任务,但是一直没有去仔细阅读详细参数配置说明以及它源码,最近花了一点时间做了一个整理。系统的看了一下源码实现并顺手做了一个简单的Demo。 一、说明 spring版本4.0.5、Quartz版本2.2.2 注意定时任务的配置需要spring-cont…

工业相机基本参数以及选型

from: https://blog.csdn.net/dcrmg/article/details/52851913工业相机基础知识(一) CCD与CMOS 工业相机按照图像的传感器元件的不同分为CCD(Charge Coupled Device,电荷耦合元件)和CMOS(金属氧化物半导体元件&#xf…

读《我是一只IT小小鸟》有感

学期刚开始老师就在课堂上给我们这些未来的IT行业工作者推荐了这本《我是一只IT小小鸟》。其实在这之前我对这本书是早有耳闻的,许多人的推荐足以证明它是一本好书,然而那时的我并未能料到自己会成为软件工程专业的学生,也对这个专业一无所知…

socket编程初级

什么是socket定义socket通常也称作套接字,用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过套接字向网络发出请求或者应答网络请求。socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件…

OpenCV—基本数据结构与示例

OpenCV的基本数据结构及示例OpenCV中强大的Mat类型大家已经比较熟悉了。这里梳理一些在工程中其他经常用到的几种基本数据类型。包括:VecScalarPointSizeRectRotatedRect1. Vec类1.1 基本概念Vec是一个模板类,主要用于存储数值向量。1.2 用法&#xff08…

使用var声明的变量 和 直接赋值并未声明的变量的区别

在看JS高级程序设计时忽然想到这个问题,众所周知,直接赋值一个变量而为声明,会产生一个全局变量(或者说是全局对象的属性),但用var声明的变量 和 直接赋值而并未声明的变量 都有哪些区别呢,这是…

转载-程序员编程技术迅速提高的终极攻略

2019独角兽企业重金招聘Python工程师标准>>> 前言 你是否觉得自己从学校毕业的时候只做过小玩具一样的程序?走入职场后哪怕没有什么经验也可以把以下这些课外练习走一遍(朋友的抱怨:学校课程总是从理论出发,作业项目都…

工作记录二-Docker+Dockerfile

1. 安装虚拟机 Oracle VM VirtualBox, 安装centos 7.2版本2. 需要在命令行中先设置代理: export http_proxyproxy.xxxxx.com:8080 3. 运行 yum install docker安装docker 安装 docker-compose curl -L https://github.com/docker/compose/releases/down…

SVM

from:https://blog.csdn.net/liugan528/article/details/79448379 SVM 1. 基本概念 支持向量机(Support Vector Machine, SVM)的基本模型是在特征空间上找到最佳的分离超平面使得训练集上正负样本间隔最大。SVM是用来解决二分类问题的有监督学…

listView当中有嵌套了有onClickListener的控件时ListView自身的onItemClick无响应的解决方案...

参考:http://www.cnblogs.com/bluestorm/archive/2013/03/24/2979557.html 解决方案 在ListView要显示的Item的外层加上 android:descendantFocusability"blocksDescendants"转载于:https://www.cnblogs.com/jinglecode/p/5683724.html

LoadRunner常用术语

1.场景 2.负载发生器 3.虚拟用户 4.虚拟用户脚本 5.事务 6.思考时间 7.集合点 8.事务响应时间 转载于:https://www.cnblogs.com/Andy-Lv/p/5263707.html