MySQL半同步(四)流程和相关参数

简介: MySQL半同步(四)流程和相关参数

源码版本5.7.29

本文作为新书《深入理解MySQL主从原理》的补充部分,供大家参考,如有误请见谅。

屏幕快照 2021-11-19 下午2.47.17.png

数据结构和流程参考:

此处不再单独列出

一、半同步的总体流程图

image.png

查看大图请移步 https://www.jianshu.com/p/5ebf4f4c1cf8

二、半同步中几个重要的状态值(主库)

半同步插件是否注册:半同步插件注册状态

ReplSemiSyncMaster::init_done_                                                                                                                                                                                                                                                                                               
 /* True when initObject has been called */                                                                                                                                                                                                                                                                                  

半同步插件是否启用:半同步开启状态

ReplSemiSyncMaster::master_enabled_

/ semi-sync is enabled on the master /
getMasterEnabled用于获取变量
set_master_enabled设置变量

完全取决于参数rpl_semi_sync_master_enabled

是否使用半同步(异步):半同步复制方式

ReplSemiSyncMaster::state_                                                                                                                                                                                                                                                                                                   
/ whether semi-sync is switched /

本状态非常重要,决定了是否是半同步复制方式,在函数ReplSemiSyncMaster::commitTrx中会完全依赖这个状态决定是否进行用户线程事务的等待,也是Rpl_semi_sync_master_status信息的来源。

三、相关参数(主库)

研究的参数包括

| rpl_semi_sync_master_enabled              | ON         |                                                                                                                                                                                                                                                                   
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
rpl_semi_sync_master_enabled

默认为false

生效点:

  • 插件初始化初始化生效,参考第一节初始化函数ReplSemiSyncMaster::initObject
  • Ack_receiver线程初始化生效,参考第一节初始化函数Ack_receiver::init
  • 参数动态生效,参考函数fix_rpl_semi_sync_master_enabled

fix_rpl_semi_sync_master_enabled函数会动态转换为半同步开启状态,并且开启Ack_receiver线程,当然根据参数rpl_semi_sync_master_wait_for_slave_countrpl_semi_sync_master_wait_no_slave

的设置,考虑是否使用同步复制方式,并且本参数会设置到 ReplSemiSyncMaster::master_enabled_ 全局变量。如果是关闭则会转化为异步复制switch_off(),并且做一些清理操作,比如active_tranxs_。

rpl_semi_sync_master_timeout

默认为10000毫秒,即10秒

生效点:

  • 等待需要的ack反馈的事务超时,生效函数为ReplSemiSyncMaster::commitTrx,如果超时那么切换为异步复制,调用switch_off函数
  • 插件初始化生效
  • 参数动态生效,参考函数fix_rpl_semi_sync_master_timeout设置方式就是赋值给ReplSemiSyncMaster::wait_timeout_
rpl_semi_sync_master_wait_for_slave_count

默认为on

本参数可以和参数rpl_semi_sync_master_wait_no_slave共同作用共同决定半同步复制还是异步复制,这里先说rpl_semi_sync_master_wait_no_slave设置on的情况

生效点:

  • 初始化Ack_recevier线程的AckContainer的元素个数,调用函数setWaitSlaveCount
  • 等待需要的ack反馈的事务超时,会通过AckContainer遍历找到最小的ack反馈点,参考repl_semi_report_binlog_sync函数
  • 动态参数修改fix_rpl_semi_sync_master_wait_for_slave_count,这里也会重新设置AckContainer的元素个数,调用函数setWaitSlaveCount

因此和rpl_semi_sync_master_timeout参数配合,可以决定收到多少个半同步从库的ack后进行反馈。

rpl_semi_sync_master_wait_no_slave

默认为on

如果为on则遵守如上rpl_semi_sync_master_wait_for_slave_count的说明,这里重点说一下它设置为false有什么作用,如果其设置为false那么会有如下影响

生效点:

  • 每次有半连接从库退出的时候,dump线程退出之前会通过回调函数repl_semi_binlog_dump_end,调入ReplSemiSyncMaster::remove_slave函数进行判断rpl_semi_sync_master_clients(现有存在的半同步从库数量)是否小于了rpl_semi_sync_master_wait_for_slave_count的个数,如果小于了则直接切换为异步复制方式。而不需要等到无ack反馈才进行切换。
  • 如果设置半同步开启状态,需要进行判断是否rpl_semi_sync_master_clients(现有存在的半同步从库数量)是否小于了pl_semi_sync_master_wait_for_slave_count的个数,如果小于则不开启同步复制。参考函数ReplSemiSyncMaster::enableMaster
  • 动态参数修改fix_rpl_semi_sync_master_wait_no_slave,根据rpl_semi_sync_master_clients(现有存在的半同步从库数量)是否为0来决定是否开启半同步复制方式,但是这里有一个疑问判断条件为rpl_semi_sync_master_clients==0。

因此本参数设置为false,设置rpl_semi_sync_master_timeout为一个很大的值,也不能保证主从一定是半同步复制。

rpl_semi_sync_master_trace_level

默认为32

我们在前面已经多次说过,如果这个参数设置16,将会有大量的半同步日志输出。这里不做描述

rpl_semi_sync_master_wait_point

默认为AFTER_SYNC,这个参数也是在前面说过了,这里不做详细描述。

生效点:

  • 主要位于回调函数repl_semi_report_commit和repl_semi_report_binlog_sync中,用于确认是在commit队列处理之前进行用户的ack反馈还是commit队列处理之后进行ack反馈。

四、重点统计值(主库)

主要研究的统计值包含

| Rpl_semi_sync_master_clients               | 0     |                                                                                                                                                                                                                                                                       
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | OFF |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
Rpl_semi_sync_master_clients:当前处于半同步复制的从库个数
  • 增加:repl_semi_binlog_dump_start回调函数调用ReplSemiSyncMaster::add_slave,及dump线程启动时刻
  • 减少:repl_semi_binlog_dump_end回调函数调用ReplSemiSyncMaster::remove_slave,及dump线程退出时刻
Rpl_semi_sync_master_no_times:关闭半同步复制方式的次数

内部为rpl_semi_sync_master_off_times

  • 增加:ReplSemiSyncMaster::switch_off函数
Rpl_semi_sync_master_no_tx:没有在半同步复制方式状态下,事务commit队列处理的次数(after_sync)/事务处理的次数(after_commit)

内部为rpl_semi_sync_master_no_transactions。

  • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数的末尾
Rpl_semi_sync_master_yes_tx:半同步复制方式状态下,事务commit队列处理的次数(after_sync)/事务处理的次数(after_commit)

内部为rpl_semi_sync_master_yes_transactions。

  • 增加:同上
Rpl_semi_sync_master_status:内部表示就是ReplSemiSyncMaster::state_,也就是当前主库状态是否处于半同步复制方式下。

参考ReplSemiSyncMaster::setExportStats函数

  • 更改就是ReplSemiSyncMaster::switch_off函数。
Rpl_semi_sync_master_wait_sessions:主要用于表示当前处于堵塞的session数量。
  • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数,进入等待前
  • 减少:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数,退出等待后但是需要注意的能够进入这个函数的是commit的leader线程,因此实际堵塞的会话数量可能是远远大于这个数字。
Rpl_semi_sync_master_tx_wait_time:主要用于表示由于等待ack反馈而等待的时间,单位微秒(百万分之1秒)

内部表示为rpl_semi_sync_master_trx_wait_time。

  • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数,等待ack之后(未超时)
Rpl_semi_sync_master_tx_waits:同上,表示次数
  • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数,等待ack之后(未超时)
rpl_semi_sync_master_wait_pos_backtraverse:降低wait_file_name_/wait_file_pos_的次数
  • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数。

五、从库参数和统计值

从库的参数和统计值很简单,和主库不同开启rpl_semi_sync_slave_enabled参数,不会动态让从库的Rpl_semi_sync_slave_status生效,启用半同步复制方式

参数rpl_semi_sync_slave_enabled:用于表示是否从库开启了半同步状态

生效点为

  • ReplSemiSyncSlave::initObject初始化的时候
  • fix_rpl_semi_sync_slave_enabled动态修改,但是需要注意这里的动态修改并不影响统计值Rpl_semi_sync_slave_status
状态值Rpl_semi_sync_slave_status:用于表示从库是否是半同步复制方式

无法动态开启这点和主库不同,并且此状态不会由于主库问题在运行期间改变,因此不能做判断半同步复制方式的根据,应该在主库判断。

改变:

  • dump线程启动时刻根据,rpl_semi_sync_slave_enabled参数和主库是否安装半同步插件来共同判定是否开启。
  • dump线程关闭时刻。

下面是一个测试(主库未安装半同步插件)

mysql> show variables like '%semi%slave_enabled';                                                                                                                                                                                                                                                                            
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
+-----------------------------+-------+
1 row in set (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

mysql> show status like '%Rpl_semi_sync_slave_status';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | OFF |
+----------------------------+-------+

可以看到Rpl_semi_sync_slave_status并未启动。

下面是另外一个测试

mysql> show slave status \G;                                                                                                                                                                                                                                                                                                 
1. row **
Slave_IO_State: Reconnecting after a failed master event read
Master_Host: 192.168.1.63
Master_User: repsem
Master_Port: 3325
Connect_Retry: 60
Master_Log_File: log_bin.000004
Read_Master_Log_Pos: 194
Relay_Log_File: relaylog.000020
Relay_Log_Pos: 363
Relay_Master_Log_File: log_bin.000004
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes

ERROR:
No query specified

mysql> show status like '%Rpl_semi_sync_slave_status';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.02 sec)

可以看到即便IO线程已经处于重连状态,Rpl_semi_sync_slave_status依旧为on。

六、运行状态下主库半同步状态切换时刻

  • 我们熟知的超过参数rpl_semi_sync_master_timeout的设置
    调用为


ReplSemiSyncMaster::commitTrx                                                                                                                                                                                                                                                                                                
->switch_off
  • 如果参数rpl_semi_sync_master_wait_no_slave设置false,那么当dump线程退出之前会判断是否小于rpl_semi_sync_master_wait_for_slave_count的设置,小于切换为异步
    调用为
repl_semi_binlog_dump_end                                                                                                                                                                                                                                                                                                    
->ReplSemiSyncMaster::remove_slave
->switch_off
  • 如果Ack_recevier线程发现反馈ack的半同步从库数量满足rpl_semi_sync_master_wait_for_slave_count的设置,尝试使用半同步复制方式
    调用为
ReplSemiSyncMaster::reportReplyPacket                                                                                                                                                                                                                                                                                        
->handleAck
->ReplSemiSyncMaster::reportReplyBinlog
->try_switch_on
  • 设置参数rpl_semi_sync_master_enabled参数的时候,会尝试使用半同步复制模式,参考上文
  • 设置参数rpl_semi_sync_master_wait_no_slave参数的时候,会尝试改变半同步复制模式,参考上文

全文完。

Enjoy MySQL :)



            </div>
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
8月前
|
云安全 NoSQL 安全
【Azure Redis】关于Redis的两个安全漏洞在Azure Redis是否修复问题:CVE-2024-51741 和 CVE-2024-46981
本文探讨了两个 Redis 漏洞(CVE-2024-51741 和 CVE-2024-46981)在 Azure Redis 上是否存在安全风险。CVE-2024-51741 可能因格式错误的 ACL 触发拒绝服务,而 CVE-2024-46981 或因恶意 Lua 脚本导致远程代码执行。目前 Azure Redis 使用版本 6.0,不受上述漏洞影响,且 Azure 云服务会及时修复漏洞以确保安全。文章强调 Azure 遵循严格的安全标准,为用户提供可靠保障。
359 4
|
Java 编译器 Android开发
解决java compiler level does not match the version of the installed java project facet
解决java compiler level does not match the version of the installed java project facet
|
NoSQL 安全 Ubuntu
CVE-2022-0543Redis Lua沙箱绕过RCE复现
CVE-2022-0543Redis Lua沙箱绕过RCE复现
816 0
|
监控 网络协议 关系型数据库
MySQL集群搭建(二)
MySQL集群搭建
220 0
|
网络协议 Java
编写Java程序,实现一个简单的echo程序(网络编程TCP实践练习)
编写Java程序,实现一个简单的echo程序(网络编程TCP实践练习)
677 0
编写Java程序,实现一个简单的echo程序(网络编程TCP实践练习)
|
2天前
|
数据采集 人工智能 安全
|
11天前
|
云安全 监控 安全