导 读

作者:高鹏(重庆八怪)

原文地址:https://www.jianshu.com/p/59c6ecb46fe5

本文为我的一些零散记录供以后参考,但里面的部分问题经常会有朋友问到,翻以往的记录比较耗时,故干脆记录下来,但是水平有限都不深入,如有误导请见谅。

为什么将这些问题放在一起讨论?主要是因为他们都存在于同一个函数MYSQL_BIN_LOG::ordered_commit函数中。

代码版本:percona 5.7.14


以下讨论sync_binlog参数在5.7中的作用

一、sync_binlog参数设置在源码中的表示

这个参数大家都知道控制着binlog的刷盘时机,但是在5.7中其实还有另外一个功能,我这里将解释他的两个功能。

我摘取了源码中说明问题的部分进行展示如下:

  • flush阶段

flush_error=process_flush_stage_queue(&total_bytes, &do_rotate,&wait_queue);//从binlog buffer或者临时文件写入到binlog文件(注意是写到kernel buffer还没做fsync),同时触发innodb的组提交逻辑,innodb组提交的逻辑代码是阿里的印风兄写的,我请教过他。
update_binlog_end_pos_after_sync= (get_sync_period() == 1);//sync_binlog参数 如果为1则为真如果不为1则为假if (!update_binlog_end_pos_after_sync)//如果sync_binlog=1则 这里不发信号给dump 如果不是1则发信号进行dumpupdate_binlog_end_pos();

其中get_sync_period()函数返回就是sync_binlog的设置,这里能够清晰看到如果sync_binlog != 1才会 在flush阶段发送信号给dump线程。

  • sync阶段

if (flush_error == 0 && total_bytes > 0) //这里进行sync binlog,{DEBUG_SYNC(thd, "before_sync_binlog_file");        std::pair<bool, bool> result= sync_binlog_file(false);sync_error= result.first;}      if (update_binlog_end_pos_after_sync) //如果sync_binlog = 1 这里才发送信号给dump线程通知进行发送binlog{THD *tmp_thd= final_queue;        while (tmp_thd->next_to_commit != NULL)tmp_thd= tmp_thd->next_to_commit;        if (flush_error == 0 && sync_error == 0)update_binlog_end_pos(tmp_thd->get_trans_pos());}

如果sync_binlog = 1 这里才会发送信号给dump线程通知进行发送binlog。
同时如果我们翻开sync_binlog_file函数的逻辑会发现这样一个逻辑:

if (force || (sync_period && ++sync_counter >= sync_period)){sync_counter= 0;

很显然这里有一个计数器sync_counter,如果当sync_binlog>1的时候才,等到sync_counter大于你设置的sync_binlog的值的时候才会触发fsync binlog(注意这里是++sync_counter 先自增再比较),这里也解释了sync_binlog>1的时候代表的是什么值,代表是组提交的次数。

二、sync_binlog参数在5.7中作用的总结
  • sync_binlog=0:binlog从不FSYNC刷盘,依赖于OS刷盘机制,同时dump线程会在flush阶段后进行binlog传输

  • sync_binlog=1:binlog每次组提交进行FSYNC刷盘,同时dump线程会在sync阶段后进行binlog传输

  • sync_binlog>1:binlog将在指定次数组提交后FSYNC刷盘,同时dump线程会在flush阶段后进行binlog传输

三、为什么这么修改

这也是一个朋友问我的问题,如果主库异常重启后,从库是否有比主库多事务的风险,实际上这个问题就是到底在什么阶段后dump线程进行传输binlog的问题。

实际上如果在flush阶段过后传输确实可能出现这个问题,而在sync阶段后传输这个时候binlog已经落盘了,就不会有这种风险了。如果出现这种错误会报错如下,这个错误也是有朋友遇到过的:

ER_SLAVE_HAS_MORE_GTIDS_THAN_MASTER
"Slave has more GTIDs than the master has, using the master's SERVER_UUID. This may indicate that the end of the binary log was truncated or that the last binary log file was lost, e.g., after a power or disk failure when sync_binlog != 1. The master may or may not have rolled back transactions that were already replicated to the slave. Suggest to replicate any transactions that master has rolled back from slave to master, and/or commit empty transactions on master to account for transactions that have been committed on master but are not included in GTID_EXECUTED."

下面开始讨论半同步中after_commit和after_sync的区别,这个问题一直也是大家讨论的重点。

四、从一个问题出发讨论

也是有很多朋友问我,其中一个问题如下:

半同步:after_sync模式
测试:超时时间设置为1个小时不让主库切换异步,同时停掉slave的I/O线程,
主库:
session1:插入一条数据hang住
session2:插入一条数据hang住
session3:插入一条数据hang住
其中session1状态为等待ACK,其他session状态为query end

问为什么其他session状态不是等待ACK而是query end。如果是after_commit模式则全部是等待ACK状态

实际上拿到这位朋友的pstack后大概就能确认大概是什么问题如下:

  • 等待ACK线程

Thread 7 (Thread 0x7f44607aa700 (LWP 24897)):
#0  0x00007f4475b02a5e in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007f44603e35d3 in ReplSemiSyncMaster::commitTrx(char const*, unsigned long long) () from /usr/local/mysql/lib/plugin/semisync_master.so
#2  0x0000000000c8197a in Binlog_storage_delegate::after_sync(THD*, char const*, unsigned long long) ()
#3  0x0000000000edd46b in call_after_sync_hook(THD*) ()
#4  0x0000000000eed935 in MYSQL_BIN_LOG::ordered_commit(THD*, bool, bool) ()
#5  0x0000000000eedf55 in MYSQL_BIN_LOG::commit(THD*, bool) ()
#6  0x000000000081e494 in ha_commit_trans(THD*, bool, bool) ()
#7  0x0000000000dce032 in trans_commit_stmt(THD*) ()
#8  0x0000000000d134e7 in mysql_execute_command(THD*, bool) ()
  • 等待LOCK_commit mutex线程

Thread 6 (Thread 0x7f4460769700 (LWP 25017)):
#0  0x00007f4475b05334 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x00007f4475b0060e in _L_lock_995 () from /lib64/libpthread.so.0
#2  0x00007f4475b00576 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x0000000000eed31f in MYSQL_BIN_LOG::change_stage(THD*, Stage_manager::StageID, THD*, st_mysql_mutex*, st_mysql_mutex*) ()
#4  0x0000000000eed5e8 in MYSQL_BIN_LOG::ordered_commit(THD*, bool, bool) ()
#5  0x0000000000eedf55 in MYSQL_BIN_LOG::commit(THD*, bool) ()
#6  0x000000000081e494 in ha_commit_trans(THD*, bool, bool) ()
#7  0x0000000000dce032 in trans_commit_stmt(THD*) ()

这里就很明显其他提交事务(这里指的是 Thread 6)堵塞在了MYSQL_BIN_LOG::change_stage函数上,其作用正是获取某个阶段的Mutex。而本线程(这里指的是 Thread 7)则是在ReplSemiSyncMaster::commitTrx上堵塞在某个Mutex上。

五、after_commit和after_sync的代码位置和区别

这里直接用代码说明进行给出,当然我只是提取了说明问题的代码片段:

  • Commit阶段

1、 change_stage(thd, Stage_manager::COMMIT_STAGE,final_queue, leave_mutex_before_commit_stage,&LOCK_commit))//持有LOCK_commit mutext进入commit阶段
2、 sync_error= call_after_sync_hook(commit_queue);//这里调用after sync hook 其在LOCK_commit保护下 此时还没有做引擎层commit
3、 process_commit_stage_queue(thd, commit_queue);//进行引擎层提交操作,具体细节以后在研究
4、 mysql_mutex_unlock(&LOCK_commit);//这里提交完成解锁队列
5、 stage_manager.signal_done(final_queue); //这里唤醒全部本组堵塞在 flush阶段的follower线程 分别做提交 但是如果是order commit 提交已经做完 这里什么都不需要做了
6、 (void) finish_commit(thd); //finish_commit会调用 atfer commit hook 其不在LOCK_commit保护下

如果抛开代码总结如下:

  • leader 持有LOCK_commit 锁 进入 commit阶段

  • 如果是设置after_sync,使用after sync 挂钩来确认ack

  • 进行引擎层提交,完成后解锁LOCK_commit 锁

  • 唤醒所有 follwer线程

  • 如果设置是after_commit,使用after commit 挂钩来确认ack

这里我们可以清楚的看到,他们的区别,实际上正如其名字一样就是说到底在那个步骤进行日志传输完成的确认,是在实际引擎层提交之前还是之后,如果是在之前则在mutex LOCK_commit的保护下,如果是在之后则不需要持有LOCK_commit mutex,这也是为什么会出现上面那个堵塞案例的原因。在5.7中默认是after_sync设置为after_sync后显然更加安全,如果是after_commit极端情况下可能引擎层已经提交完成,事务对主库可见,但是从库还没有传输完成如果从库奔溃可能出现少事务的情况。


结语

对于5.7中安全的设置应该尽量保证sync_binlog=1同时设置rpl_semi_sync_master_wait_point为after_sync,这实际上都是默认设置。

对本文有任何疑问可扫码添加原文作者微信



加入QQ技术交流群

扫码加入知数堂4群-王者峡谷

(QQ群号:650149401)

MySQL 5.7中sync_binlog参数和半同步中after_commit和after_sync的区别相关推荐

  1. mysql sync_binlog 作用_mysql 中 sync_binlog 参数作用

    sync_binlog":这个参数是对于MySQL系统来说是至关重要的,他不仅影响到Binlog对MySQL所带来的性能损耗,而且还影响到MySQL中数据的完整性.对于"sync_ ...

  2. mysql的主从,主主,半同步

    主配置文件 [mysqld] datadir=/data/mydata log-bin=/data/binlogs/master-bin socket=/var/lib/mysql/mysql.soc ...

  3. mysql主从(一)--搭建(GTID+row+增强半同步)

    文章目录 1.主从搭建 1.1.mysql5.7 GTID+row+增强半同步 1.1.1.主从库环境准备 1.1.2.主库(3309)备份数据,在从库(3306)恢复 1.1.3.创建复制用户 1. ...

  4. mysql主主复制、主从复制、半同步的实现

    实验前提:两台服务器 Master server:172.16.23.1 slave server:172.16.23.2 一.mysql主从服务器实现 简单介绍: MySQL支持单向.异步复制,复制 ...

  5. Yarn管理界面中各个参数和yarn-site.xml中参数的对应关系

    启动集群后,打开master:8088/cluster/nodes 然后打开: master:8088/cluster/scheduler 上图中右侧的73.2%≈4.39 GB/6GB=0.7316 ...

  6. java中重载 参数顺序_Java方法中的参数太多,第4部分:重载

    java中重载 参数顺序 期望将过多的参数传递给Java方法的问题之一是,该方法的客户端很难确定它们是否以适当的顺序传递了适当的值. 在以前的文章中,我描述了如何使用自定义类型 , 参数对象和构建器来 ...

  7. Hibernate的HQL中in参数设置和JdbcTemplete中的in参数

    写代码的时候突然忘记了,在此记录一下: Hibernate的HQL中in参数设置 public void updateDeviceByIDS(Long[] devicepkarr, DeviceINF ...

  8. Java中非法参数的异常_Java中的异常

    异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API中Throwable类的众多子类描述各种不同的异常. ...

  9. Vue中向js中传递参数并在js中定义对象并转换参数

    场景 有下面这种主从表结构 上面的信息是主表的信息,下面是从表的信息. 在Vue中将页面的信息传递到js的方法中,在js方法中将参数进行转换使其与后台接收的参数相匹配. 注: 博客: https:// ...

最新文章

  1. 计算机文化基础案例教程第三版答案,计算机文化基础案例教程(第3版 谭宁)教学课件 素材.zip-排骨做法.doc...
  2. 11.2.4 jQuery动画
  3. JS定时器使用,定时定点,固定时刻,循环执行
  4. 怎样设置电脑壁纸_怎样设置电脑的资料定时备份到移动硬盘里
  5. drools 7.11.0.Final使用
  6. k8s 离线安装_使用 Kind 在离线环境创建 K8S 集群
  7. linux重启mysql一直_linux正确重启MySQL的方法
  8. mysql表 spid program_SQL Server 表,记录 死锁解决办法
  9. 利用iis服务器创建站点,如何使用iis建立一个网站
  10. 服务器主板如何连接无线网卡,无线网卡如何设置WiFi共享模式?
  11. cad图层置顶的lisp_cad中如何将一个图层置于上层
  12. 关于Outline Effect 高亮插件不能生效-爻览SDK-MR混合现实开发日志
  13. 算法与数据结构(邓俊辉)第一章
  14. scheme唤醒app-抖音
  15. Mina MEID Activator 2.120210512更新使用说明支持三网(移动、联通、电信)国行版手机解锁打电话4G苹果手机激活锁停用Hello密码锁绕ID屏幕锁密码
  16. Jetpack Paging3 基本使用
  17. 当STM32遇上RFID
  18. 如何创建兆丰菜单Twitter的追随者复选标记分析与Icontact
  19. java des加密结果不一样_Java和C#使用DES加密结果不一致
  20. awk的真实使用案例及区间分布统计工具histogram.py

热门文章

  1. Axure RP 基础元件
  2. 关于自学HTML+CSS+JS的日子
  3. Reinforcement Learning,微信公众号:DRL学习
  4. VAS价值存托公链体系创世录 第一章
  5. Smart3D将已经生成的OSGB格式的模型转换成S3C格式
  6. 思维导图怎么画?思维导图快速绘制教程
  7. 【图像压缩】DCT图像压缩(压缩率可调)【含GUI Matlab源码 1049期】
  8. 从 PC 解锁 Android 手机的 6 种有效方法
  9. 转播小助手开启微信语音多群同步直播转播之路
  10. html文本框后面加一个按钮怎么对齐,怎样对齐文本框和图像(image)按钮实现三点一线...