目录

  1. 问题
  2. 关于半同步复制
  3. 代码层面解释上面几个问题

1 问题

对于MySQL半同步复制,了解MySQL的人,都肯定能说出一二,比如和异步复制、同步复制的差别、超时退化为异步复制和无损复制等,但是这面有以下几个问题(基于MySQL版本为社区版5.7.21):

  • 主库在什么时候调用半同步插件?
  • 主库以什么为单位发送binlog日志?
  • 主库会对二进制日志做额外处理吗?
  • 从库以什么为单位来处理发送过来的日志信息
  • 从库什么时候发送ACK给到主库?
  • 当主库设置了多个ACK后,主库怎么判断收到的ACK的个数,即确认的位置点?

对于上面的几个问题,这面进行简单的回答,所以如果不想看其他部分的,直接看完这一部分就可以了。

  1. 主库在什么时候调用半同步插件?
    MySQL在server层引入了组提交后,为了提高并行度,将提交阶段分为了flush、sync和commit阶段,根据sync_binlog设置的不同,会在flush阶段(sync_binlog设置为非1)或sync阶段(sync_binlog设置为1)以更新binlog位置点的方式通知dump线程发送binlog,而在commit阶段等待从库的ACK应答情况,这面又分为两个不同的等待位置点,即rpl_semi_sync_master_wait_point参数是after_sync还是after_commit。
  2. 主库以什么为单位发送binlog日志?
    主库会以event为单位将binlog日志写入到net_buffer里面,但是并不会立即发送,而是达到条件后一起发送给从库。
  3. 主库会对二进制日志做额外处理吗?
    答案是肯定的,主库读取每个event后,在发送之前都会在event头部添加两个字节的内容,第一个字节是固定的0xef,第二个字节表示是否需要从库收到后发送ACK回包信息,所以对于从库的ACK的回包是以组提交里面一组事务为单位(之前有同事问我ACK确认包以什么为单位,我这面回答是event为单位,羞愧)。
  4. 从库以什么为单位来处理发送过来的日志信息?
    从库接收到主库发送过来的binlog日志后,也是通过event为单位进行读取、根据sync_relay_log设置写入到ralaylog文件里面。
  5. 从库什么时候发送ACK给到主库?
    问题3里面已经简单介绍了主库对event的处理,所以从库在读取发送过来的event后,根据前两个字节判断是否需要发送ACK包。
  6. 当主库设置了多个ACK后,主库怎么判断收到的ACK的个数?
    主库这面维护了一个ACK数组,数组的大小设置为rpl_semi_sync_master_wait_for_slave_count值N-1,当rpl_semi_sync_master_wait_for_slave_count为1时,用不到该数组。数组里面记录了以N-1个以从库的server_id为标识,确认的位置点,当收到一个新的ACK包时,通过server_id进行判断,如果不在数组里面,并且数组已经满了,说明收到了N个确认包,找到最小的确认位置点,等待在这个位置点或者之前的所有连接均可以返回成功。

2 关于半同步复制

下面简单介绍一下半同步复制,MySQL的半同步复制是在MGR出来之前的平衡性能和数据一致性的最好的解决方案,尤其在组提交、无损复制和并行复制出来之后。对于并行复制,writeset的判断方式的出现更是解决了主库并发不高的情况下,从库的并行回放的问题(MySQL在5.7.22和8.0.1里面添加了binlog_transaction_dependency_tracking参数用来标记主库通过什么方式来判断事务是否能在从库并行回放,同事测试发现对于设置成WRITESET会比COMMIT_ORDER TPS损耗10%左右,因为这面如果设置成WRITESET,系统会在原来的基础上多加一次通过hash表last_committed值的计算。而当binlog_transaction_dependency_history_size的值,即hash表的个数设置为默认25000和10时,测试TPS发现,设置为10的TPS却比25000的更高,查看代码发现hash表的实现时通过std::map实现,而std::map是通过红黑树实现,这面会需要对比更多的次数,导致性能差一些,后面估计会改成hash_map来实现,这面不具体说明)。MySQL的半同步插件、GTID等这些特性,使得实现一套高可用的方案更加简单,高可用软件只需要解决主节点可用性的检测、通过GTID的对比选择提升哪个从库为新主和最后一个事务的处理等问题即可。当然实现的过程中,需要注意很多细节,比如半同步插件rpl_semi_sync_master_wait_for_slave_count、rpl_semi_sync_master_timeout值的设置。对于数据一致性要求比较高的业务场景,都会避免半同步因为从库长时间没有回应ACK包退化为异步复制,所以将rpl_semi_sync_master_timeout设置为一个比较大的数字,使得半同步不退化,而对于rpl_semi_sync_master_wait_for_slave_count参数,则需要应场景设置,表示需要多少个从库收到事务的日志主库才返回给客户端成功。虽然半同步插件已经解决了一致性和性能大部分问题,但是相比较于MySQL的复制的最新的解决方案MGR,还是问题比较多,比如多写的问题,可以说MGR是复制的最终解决方案(现在MGR还是不够成熟,之前使用的时候就遇到过因为网络问题,导致某个节点上面的GTID对应的事务和别的节点上面的不同的问题,最终导致数据不一致的问题)。对于开源的高可用解决方案里面借助半同步来做高可用的也是很多,比如青云的分布式数据库RadonDB的下面的存储节点,GitHub上面介绍的图如下:

这面Raft算法是借助GTID来进行选主,而不是为了数据和同步日志,日志的同步这面还是用了半同步复制,将rpl_semi_sync_master_wait_for_slave_count设置为1,正常写入后,肯定会有一个从库收到了事务的日志信息,并且将rpl_semi_sync_master_timeout设置为999999,可以认为无限大,不会发生退化为异步的问题。

3 代码层面解释上面几个问题

下面根据MySQL代码解释上面的几个问题,再次强调参考的代码为MySQL社区版5.7.21。

我们先查看主库的处理逻辑,首先查看sql/http://binlog.cc里面的提交的逻辑,下面贴一下主要代码:

int 

可以发现上面对于sync_binlog不同的值,通知dump线程发送binlog的位置点也是不一样的:

  • sync_binlog设置为1: 在sync阶段通知dump 线程发送binlog,这时候binlog确定已经刷盘,因为在flush阶段只是将binlog刷新到了文件缓存,如果发生了宕机,有可能丢失,这个时候如果从库已经收到了,导致从库比主库数据多。
  • sync_binlog设置为非1: 在flush阶段通知dump线程发送binlog。

对于上面说的咋flush阶段调用的Binlog_storage_observer里面的repl_semi_report_binlog_update函数,里面的调用如下:

--

对于dump线程发送binlog日志的逻辑,调用的逻辑如下:

--

下面重点说明一下repl_semisync.updateSyncHeader函数,部分代码如下:

int 

对于从库的接收发送过来的二进制文件,以及处理逻辑,见http://rpl_slave.cc里面的handle_slave_io函数,里面的调用的逻辑为:

--

对于主库的ACK线程的处理逻辑如下:

--

对于上面一直通过文件名和位置点进行对比,会不会有问题呢?答案是否定的,因为binlog的文件名是递增的,如果没有执行reset master命令,这个文件名会一直增加,当然到了超过了最大值之后(2^31-1),会报错,需要重启数据库。

sync是同步还是非同步_MySQL半同步复制你可能没有注意的点相关推荐

  1. mysql 半同步 原理_MySQL半同步复制原理与配置详解

    一 .异步.同步和半同步复制概念 异步复制(Asynchronous replication),MySQL默认的复制是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已 ...

  2. mysql 半同步复制_Mysql半同步复制原理及问题排查

    mysql半同步复制和异步复制的差别如上述架构图所示:在mysql异步复制的情况下,Mysql Master Server将自己的Binary Log通过复制线程传输出去以后,Mysql Master ...

  3. mysql半备份_MySQL半同步复制与增强半同步复制详解及安装

    一.基础 1.目前MySQL主要有三种复制方式 1)异步复制 2)半同步复制 3)增强半同步复制 推荐使用:对性能要求较高的推荐使用异步复制 ,如果运行的金融类业务推荐使用增强半同步复制,并使用ROW ...

  4. mysql半复制_mysql半同步复制

    从MySQL5.5开始,MySQL以插件的形式支持半同步复制.如何理解半同步呢?首先我们来看看异步,全同步的概念 异步复制(Asynchronous replication) MySQL默认的复制即是 ...

  5. mysql半同步降级_MySQL半同步复制

    半同步复制简介 MySQL复制默认情况下是异步的,主库将事件写入binlog并不管从库是否接受并处理它们,如果主库崩溃时,已提交的事务可能没有被传送到从库,因此主从切换可能导致数据丢失.Semisyn ...

  6. mysql semisync 恢复_mysql半同步复制(semi_sync_replication)搭建及使用

    mysql半同步复制(semi_sync_replication)搭建及使用 google为mysql开发了一个补丁一个基于半同步的补丁,应用与mysql5.0.回来mysql打上了该补丁,并在5.5 ...

  7. Mysql增强半同步模式_MySQL半同步复制与增强半同步复制详解及安装

    一.基础 1.目前MySQL主要有三种复制方式 1)异步复制 2)半同步复制 3)增强半同步复制 推荐使用:对性能要求较高的推荐使用异步复制 ,如果运行的金融类业务推荐使用增强半同步复制,并使用ROW ...

  8. mysql 半同步 配置_Mysql 半同步复制配置

    以下是配置和监控半同步复制: 1. 半同步复制功能以plugin的方式接入MySQL,需要在主库与从库两端同时开启半同步的支持,具体配置如下: On the master mysql> INST ...

  9. mysql半同步模式_MySQL 半同步复制模式的实现

    半同步复制原理图 #半同步启动需要主从两端都需要加载安装各自对应的semi模块,从库端支持半同步功能的数量至少一台:主库端当一个事务成功提交后,并不及时反馈给前端用户,该线程会被临时block,等待由 ...

最新文章

  1. GCC对C++标准的实现情况
  2. 让您的Eclipse具有千变万化的外观 1
  3. 5月学习总结(Ant-Design,mustache,require.js,grunt)
  4. python中import sys_python import sys出错怎么办
  5. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第33篇]Bellcore攻击是如何攻击使用CRT的RSA的?
  6. 软件工程师 VS 硬件工程师
  7. matlab knn实现,Matlab之KNN实现
  8. 视频编码会议_我在编码事件和会议上进行了16次技术演讲。 这是我学到的。
  9. TensorFlow tf.squeeze
  10. HIbernate Session 线程安全的问题
  11. 关于家庭路由器网络布线
  12. android usb独占模式,Android USB主机模式和附件模式
  13. ZigBee的应用场景
  14. NI ELVIS III模拟电子电路课程实验解决方案
  15. Internet Explorer 无法打开该 Internet 站点。请求的站点不可用
  16. BT宝塔面板设置网站自动云备份——备份到七牛云或腾讯COS
  17. 设计模式C++——命令模式(高屋建瓴)
  18. 分支函数c语言,C语言练习题2(分支结构 循环结构 数组 函数2009-2012二级真题 ).doc...
  19. 内网穿透-----ngrok服务器搭建
  20. 报错UnicodeEncodeError: ‘ascii‘ codec can‘t encode character ‘\u7b2c‘ in position 64: ordinal not in r

热门文章

  1. linux上给其他在线用户发送信息(wall, write, talk, mesg)
  2. iOS核心动画高级技术(十三) 高效绘图
  3. C#复制、粘贴文本信息到剪贴板
  4. 对textfield的键盘改造成滚动选择器而不是输入键盘
  5. Hello,Akka
  6. Android启动画面实现
  7. MyBatis 注释
  8. javascript弹出窗口居中代码
  9. 每日算法练习之最大公约数最小公倍数
  10. 优化算法optimization:AdaGrad