mysql半同步(semi-sync)源码实现
mysql复制简单介绍了mysql semi-sync的出现的原因,并说明了semi-sync如何保证不丢数据。这篇文章主要侧重于semi-sync的实现,结合源码将semi-sync的实现过程展现给大家。最新的semi-sync源码可以参考官方5.7版本的实现,https://github.com/mysql/mysql-server。
打开semi-sync的正确姿势
默认情况下的mysql复制都是异步复制,mysql通过参数来控制semi-sync开关。具体而言,主库上通过rpl_semi_sync_master_enabled参数控制,备库上通过rpl_semi_sync_slave_enabled参数控制,打开这两个参数后,mysql semi-sync的特性就打开了。注意对于备库而言,为了保证半同步立即生效,需要重启slave的IO线程。另外,还有一个比较重要的参数是rpl_semi_sync_master_timeout,这个参数用于控制master等待semi-slave ack报文的时间,单位是毫秒,默认是10000。master等待超时,则切换为普通的异步复制。
master:
set global rpl_semi_sync_master_enabled=1;
set global rpl_semi_sync_master_timeout=xxx; slave:
stop slave io_thread;
set global rpl_semi_sync_slave_enabled=1;
start slave io_thread;
另外需要注意的是,打开了上述两个参数只说明master-slave已经具备打开semi-sync的基本条件了,但复制是否依照半同步运行,还需要根据Rpl_semi_sync_master_status的状态值确定。因为比如slave较master有很大延迟(超过rpl_semi_sync_master_timeout),那么复制切换为普通复制。对于需要调试代码的童鞋而言,rpl_semi_sync_master_trace_level和rpl_semi_sync_slave_trace_level非常重要,通过设置level取值,可以打印日志记录半同步的详细过程,方便定位问题。
semi-sync的实现
semi-sync说到底也是一种复制,只不过是在普通的复制基础上,添加了一些步骤来实现。因此semi-sync并没有改变复制的基本框架,我们的讨论也从master,slave两方面展开。
1.master(主库)
主库上面主要包含三个部分,(1).负责与slave-io线程对接的binlog dump线程,将binlog发送到slave,(2).主库上写事务的工作线程,(3).收取semi-slave报文的ack_receiver线程。
(1).binlog dump流程
主要执行逻辑在mysql_binlog_send函数中。
1.判断slave是否是semi_slave,调用add_slave将semi-slave加入到ack_receiver线程的监听队列中。判断的逻辑是slave对应的会话上是否设置了参数rpl_semi_sync_slave。
2.根据slave的请求偏移和binlog文件,从指定位点读取binlog
3.根据文件和位点,捞binlog文件中的数据
4.调用updateSyncHeader设置数据包头semi-sync标记
根据实时semi-sync运行状态来确定是否设置(这个状态由ack_receiver线程根据是否及时收到slave-ack报文设置)
5.调用my_net_write发送binlog
6.调用net_flush确认网络包发送出去
如果当前所有产生的binlog已经处理完,需调用wait_for_update_bin_log等待binlog更新。
(2).半同步事务提交流程
mysql5.6以后提交采用组提交方式,主要分为三个阶段,每个阶段有一个队列,增加semi-sync后,又增加了一个semi-sync阶段。
1.flush阶段:
队列能保证写binlog的顺序与innodb-commit的顺序一致。通过队列,可以保证顺序写每个事务的binlog-cache,然后只进行一次write操作(flush_cache_to_file)。flush阶段后,如果sync_binlog不是1,则通知master有新binlog产生;如果sync_binlog为1,则等待sync阶段后,再通知dump线程有新binlog产生。这里我理解是因为如果不为1,则可能没有后续的sync阶段,而操作系统缓存也有binlog数据,所以可以在flush阶段后通知;而对于sync_binlog为1的情况,可以保证主库的binlog先落地,永远比备库多。但如果sync_binlog不为1,比如1000,则主机异常情况下,则可能出现备库的binlog比主库还多的情况。根据sync_binlog的设置,确认是否要跳过sync阶段。
2.sync阶段:
sync_binlog_file
3.semi_sync阶段:
call_after_sync,等待备库应答。调用cond_timewait等待条件变量&COND_binlog_send_,注意这里只是leader线程在等,将leader线程唤醒后,才会结束semi_sync阶段,进而唤醒其它的follower线程。
4.commit阶段:
innodb-commit
waitAfterCommit,等待备库应答。调用cond_timewait等待条件变量&COND_binlog_send_ 。最终我们根据semi-sync复制模式的设置(AFTER_COMMIT,AFTER_SYNC),来确定是第(3)步还是第(4)步进行等待。
(3).接收slave-ack报文流程
这个流程的工作主要在ack_receiver线程中,这个线程的主要作用是监听semi-slave的ack包,确认master-slave链路是否工作在半同步状态,并根据实际运行状态将普通复制与半同步复制进行切换。打开主库rpl_semi_sync_master_enabled参数后,该线程启动,关闭参数后,该线程消亡。
流程如下:
1.遍历semi-slave数组
2.通过select函数监听每个slave是否有网络包过来
3.调用my_net_read读取包数据
4.调用reportReplyPacket处理semi-sync复制状态
若备库已经获取了最新的binlog位点,则唤醒等待的工作线程
5.调用reportReplyBinlog唤醒等待的线程,mysql_cond_broadcast(&COND_binlog_send_);
2.slave(备库)
主要实现在(handle_slave_io)
1.启动io-thread后,调用safe_connect建立与master的连接
2.调用request_dump函数处理请求binlog逻辑
(1).执行命令SET @rpl_semi_sync_slave= 1,设置一个局部变量,通过这个参数标记slave为semi-slave
(2).发送命令COM_BINLOG_DUMP请求日志
循环从master端收取日志,处理日志
{
1.调用read_event,从master端收取日志(如果没有网络包,会阻塞等待)
2.调用slaveReadSyncHeader,确定网络包头是否有semi-sync标记
3.调用queue_event将日志写入relay-log,在这个过程中会过滤自身server-id的日志
4.如果有semi-sync标记,调用slaveReply函数,发送ack报文
}
mysql半同步(semi-sync)源码实现的更多相关文章
- MySQL半同步复制源码解析
今天 DBA 同事问了一个问题,MySQL在半同步复制的场景下,当关闭从节点时使得从节点的数量 < rpl_semi_sync_master_wait_for_slave_count时,show ...
- Mysql半同步复制模式说明及配置示例 - 运维小结
MySQL主从复制包括异步模式.半同步模式.GTID模式以及多源复制模式,默认是异步模式 (如之前详细介绍的mysql主从复制).所谓异步模式指的是MySQL 主服务器上I/O thread 线程将二 ...
- mysql半同步复制问题排查
1.问题背景 默认情况下,线上的mysql复制都是异步复制,因此在极端情况下,主备切换时,会有一定的概率备库比主库数据少,因此切换后,我们会通过工具进行回滚回补,确保数据不丢失.半同步复制则 ...
- 安装MySQL半同步复制
一.简介 从MySQL5.5开始,MySQL以插件的形式支持半同步复制.如何理解半同步呢?首先我们来看看异步,全同步的概念 异步复制(Asynchronous replication) MySQL默认 ...
- MySQL半同步复制搭建
默认情况下,MySQL 5.5/5.6/5.7和MariaDB 10.0/10.1的复制是异步的,异步复制可以提供最佳性能,主库把binlog日志发送给从库,这一动作就结束了,并不会验证从库是否接收完 ...
- mysql半同步复制跟无损半同步区别
mysql半同步复制跟无损半同步复制的区别: 无损复制其实就是对semi sync增加了rpl_semi_sync_master_wait_point参数,来控制半同步模式下主库在返回给会话事务成功之 ...
- MySQL半同步复制
从MySQL5.5开始,MySQL以插件的形式支持半同步复制.如何理解半同步呢?首先我们来看看异步,全同步的概念 异步复制(Asynchronous replication) MySQL默认的复制即是 ...
- MySQL半同步安装以及参数
MySQL半同步安装以及参数 基于MySQL5.5 官档地址: Semisynchronous Replication Administrative Interface https://dev.mys ...
- MySQL 半同步重要状态参数说明
如果配置了MySQL半同步复制,可以在主库查询半同步状态,命令为: SHOW GLOBAL STATUS LIKE '%semi%'; 参数说明 Rpl_semi_sync_master_c ...
- mysql半同步复制实现
mysql半同步复制和异步复制的区别如上述架构图所看到的:在mysql异步复制的情况下.Mysql Master Server将自己的Binary Log通过复制线程传输出去以后,Mysql Mast ...
随机推荐
- 自学MVC看这里——全网最全ASP.NET MVC 教程汇总
MVC架构已深得人心,微软也不甘落后,推出了Asp.net MVC.小编特意整理博客园乃至整个网络最具价值的MVC技术原创文章,为想要学习ASP.NET MVC技术的学习者提供一个整合学习入口.本文从 ...
- Win下必备利器之Cmder
诚言,对于开发码字者,Mac和Linux果断要比Windows更贴心;但只要折腾下,Windows下也是有不少利器的.之前就有在Windows下效率必备软件一文中对此做了下记载:其虽没oh-my-zs ...
- Atitit 数据存储视图的最佳实际best practice attilax总结
Atitit 数据存储视图的最佳实际best practice attilax总结 1.1. 视图优点:可读性的提升1 1.2. 结论 本着可读性优先于性能的原则,面向人类编程优先于面向机器编程,应 ...
- HTML5 之拖放(drag与drop)
拖放(Drag 和 drop)是 HTML5 标准的组成部分. 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. HTML5 拖放实例 ...
- Oracle AWR报告提取方法
本文旨在用来指导项目人员自行提取Oracle数据库的AWR报告. 1.当前连接实例的AWR报告提取:@?/rdbms/admin/awrrpt 2.RAC的其他实例AWR报告提取:@?/rdbms/a ...
- android使用PullToRefresh实现上拉加载和下拉刷新效果
其实很早前就在博客园中也写过官方的下拉刷新控件SwipeRefreshLayout,但是这个控件仅仅支持下拉刷新,用起来还算可以.然而在我们实际开发应用中,很多地方都不止有下拉刷新,而且还有上拉加载的 ...
- 你真的会玩SQL吗?Case也疯狂
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- Android测试提升效率批处理脚本(三)
前言: 前面放出过几次批处理,这次只放一个环境检查的被管理员给打回来了,不得不再找找几个有含金量的放出来,请看正文~~~ 目录 1.Android环境检查 2.Android内存监控 3.模拟蓝牙手柄 ...
- jQuery-1.9.1源码分析系列完毕目录整理
jQuery 1.9.1源码分析已经完毕.目录如下 jQuery-1.9.1源码分析系列(一)整体架构 jQuery-1.9.1源码分析系列(一)整体架构续 jQuery-1.9.1源码分析系列(二) ...
- Django models对象的select_related方法(减少查询次数)
表结构 先创建一个新的app python manage.py startapp test01 在settings.py注册一下app INSTALLED_APPS = ( 'django.contr ...