图解MySQL | [缺陷分析]半同步下多从库复制异常

本文转载自[图解MySQL],原创作者:王悦,黄炎,周海鸣

​引  言

本文是由爱可生研发团队出品的「图解MySQL」系列文章,不定期更新,但篇篇精品。

爱可生开源社区持续运营维护的小目标:

  • 每周至少推送一篇高质量技术文章

  • 每月研发团队发布开源组件新版

  • 每年1024开源一款企业级组件

  • 2019年至少25场社区活动

欢迎大家持续关注~

本文分析的缺陷是MySQL bug#89370,其主要的现象是:配置半同步(复制)到多个从库,部分从库在一段时间内无法复制数据,但所有复制状态均正常。

 


缺陷的复现

MySQL版本:5.7.16,5.7.17,5.7.21

  1. 配置半同步一个master两个slave,设置master的

    rpl_semi_sync_master_wait_for_slave_count=2,保持一定数据压力

  2. 检查master的

    rpl_semi_sync_master_status状态为ON,确保半同步没有退化为异步

  3. 设置master的

    rpl_semi_sync_master_wait_for_slave_count=1

  4. 重启一个slave “stop slave; start slave” 

 

可以观察到步骤4中重启的那个slave长达数分钟不会有master的复制数据流入,但查看复制状态均正常。

 


 

缺陷的原理图解 

 

图一:描述了半同步复制的大致流程

  • 上图中按序解析了MySQL半同步插件在binlog group commit中扮演的角色:

 

binlog group commit分为三个阶段:

  1. Flush Phase(图中序号2):  将一组事务写入binlog缓存区,向半同步插件注册事务(图中序号2.1),更新binlog文件位置信息(图中序号2.2)

  2. Sync Phase(图中序号4):  对binlog做fsync操作,将一组事务一起刷入磁盘

  3. Commit Phase(图中序号5):  等待半同步完成,在引擎层提交事务

     

半同步插件

  1. 图中序号3:在binlog完成位置信息更新后,开始通过复制线程读取binlog文件,将其中的event发送给slave  

  2. 图中序号5.1:将事务复制完成信息返回master,master根据该信息确定是否可以提交事务

  • MySQL从5.5版本后引入了半同步插件,以解决传统异步复制在master节点宕机时可能出现的数据丢失。

  • 开启半同步能够保证master接收到的事务,在得到至少一个slave接收确认之后再返回给客户端。

  • MySQL 5.6版本之前存在一个著名的bug#13669,在开启binlog时为了保证引擎层与binlog的提交顺序一致,使得group commit机制失效。从5.6版本后才真正引入了binlog的group commit,在保证引擎层和binlog事务最终一致的情况下,大幅提高了高并发场景下的处理性能。

 

图二:描述了MySQL 5.6版本中的ACK接收机制

 

  • 在MySQL 5.6版本的实现里,master的复制线程同时负责发送事务和接收slave返回的ACK消息,当没有接收到上一个事务的ACK消息之前,无法发送下一个事务。如此串行化的机制成为了半同步的性能瓶颈。

 

图三:描述了MySQL 5.7版本中的ACK接收机制

 

  • 在MySQL 5.7版本的实现里,将接收ACK这部分任务从master的复制线程中拆分出来,由半同步插件的ACK接收线程单独处理,使得事务发送和接收ACK得以并行,极大提高了半同步性能。

 

图四:描述了本文缺陷的发生原因

 

  • 本文所要描述的缺陷就出现在ACK接收线程中,ACK线程(图中序号1)和复制线程(图中序号2)在抢占互斥锁时产生了竞争。

  • master在监听slave的ACK消息时,无限的while循环使得ACK线程基本时刻占有互斥锁。当启动另一个slave时,master的新复制线程无法在短时间内抢占该互斥锁,导致复制线程无法启动成功,造成了slave的slave_io_thread 停滞,无法复制数据的现象。

 


 

扩展阅读

  • https://bugs.mysql.com/bug.php?id=89370

  • https://bugs.mysql.com/bug.php?id=13669

  • https://kristiannielsen.livejournal.com/12254.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值