MySQL半同步复制配置后性能降低,如何调整rpl_semi_sync参数提升效率?
- 内容介绍
- 文章标签
- 相关推荐
本文共计887个文字,预计阅读时间需要4分钟。
由于 `rpl_semi_sync_master_wait_for_slave_count` 默认是 1,数据库必须等待至少一个从库返回 ACK 才能提交事务;而 ACK 并非日志落盘完成,只是接收并写入 relay log 缓冲区 —— 但网络延迟、从库负载高、乃至 TCP 接收队列积压,都可能导致等待卡在主库的 `commit`。
- 默认行为下,哪怕从库只慢 50ms,主库每条写事务就多等 50ms,QPS 直接腰斩
-
rpl_semi_sync_master_timeout单位是毫秒,但设太小(比如 100)会导致频繁退化为异步,失去半同步意义;设太大(比如 10000)又放大延迟风险 - MySQL 5.7+ 的
rpl_semi_sync_master_wait_point设为AFTER_SYNC(默认)比AFTER_COMMIT更安全,但也更慢——它要求主库先刷 binlog、再等 ACK,最后才提交本地事务
如何调低延迟又不丢数据
核心思路:不让主库“傻等”,而是用超时 + 自适应降级 + 精准 ACK 控制。
- 把
rpl_semi_sync_master_timeout设为 1000(1 秒),这是多数内网环境的合理平衡点:短于 RTT 波动峰,长于正常 ACK 延迟 - 启用
rpl_semi_sync_master_wait_point = AFTER_SYNC,确保主库 binlog 已刷盘再等 ACK,避免主库 crash 后丢失已确认事务 - 如果从库有多个,把
rpl_semi_sync_master_wait_for_slave_count保持为 1,别设成 2——等两个从库 ACK 是自找死路,不是高可用,是高延迟 - 监控
Rpl_semi_sync_master_no_times和Rpl_semi_sync_master_off_times,一旦发现频繁降级,说明网络或从库 IO 真有问题,得查SHOW PROCESSLIST里从库线程状态,而不是调参数
哪些配置组合会悄悄拖垮性能
这些看似“加强可靠性”的设置,实际在生产中常成为性能黑洞。
-
rpl_semi_sync_master_wait_point = AFTER_COMMIT:主库先提交再发 binlog,主从不一致窗口变大,且无法防止主库 crash 后事务丢失;还容易和sync_binlog=1冲突,触发双刷盘 -
sync_binlog=1+innodb_flush_log_at_trx_commit=1+ 半同步:三重刷盘叠加等待,单事务延迟可能突破 10ms,尤其 SSD 负载高时 - 从库上开了
slave_parallel_workers > 0但没配slave_parallel_type=LOGICAL_CLOCK:可能导致 ACK 发送延迟不可控,因为 SQL 线程还没真正执行完就返回了 relay log 接收确认
验证半同步是否真在工作
别只看 SHOW VARIABLES LIKE 'rpl_semi_sync%' 全是 ON 就放心——那只是开关开了,不代表正在生效。
- 执行
SELECT * FROM performance_schema.replication_applier_status_by_coordinator;,检查LAST_ERROR_MESSAGE是否为空 - 查
SHOW STATUS LIKE 'Rpl_semi_sync%';,重点关注Rpl_semi_sync_master_status(是否 ON)、Rpl_semi_sync_master_yes_tx(成功半同步事务数)和Rpl_semi_sync_master_no_tx(失败回退数),二者比值持续低于 95%,说明链路不稳定 - 在主库执行
INSERT后立刻查SELECT @@global.rpl_semi_sync_master_status;,如果刚插入完就变成 OFF,大概率是rpl_semi_sync_master_timeout太小或从库挂了
真正难的不是配参数,是区分“配置生效了”和“链路稳住了”——后者得看持续几分钟的 Rpl_semi_sync_master_yes_tx 增速,而不是某次 SHOW STATUS 的快照。
本文共计887个文字,预计阅读时间需要4分钟。
由于 `rpl_semi_sync_master_wait_for_slave_count` 默认是 1,数据库必须等待至少一个从库返回 ACK 才能提交事务;而 ACK 并非日志落盘完成,只是接收并写入 relay log 缓冲区 —— 但网络延迟、从库负载高、乃至 TCP 接收队列积压,都可能导致等待卡在主库的 `commit`。
- 默认行为下,哪怕从库只慢 50ms,主库每条写事务就多等 50ms,QPS 直接腰斩
-
rpl_semi_sync_master_timeout单位是毫秒,但设太小(比如 100)会导致频繁退化为异步,失去半同步意义;设太大(比如 10000)又放大延迟风险 - MySQL 5.7+ 的
rpl_semi_sync_master_wait_point设为AFTER_SYNC(默认)比AFTER_COMMIT更安全,但也更慢——它要求主库先刷 binlog、再等 ACK,最后才提交本地事务
如何调低延迟又不丢数据
核心思路:不让主库“傻等”,而是用超时 + 自适应降级 + 精准 ACK 控制。
- 把
rpl_semi_sync_master_timeout设为 1000(1 秒),这是多数内网环境的合理平衡点:短于 RTT 波动峰,长于正常 ACK 延迟 - 启用
rpl_semi_sync_master_wait_point = AFTER_SYNC,确保主库 binlog 已刷盘再等 ACK,避免主库 crash 后丢失已确认事务 - 如果从库有多个,把
rpl_semi_sync_master_wait_for_slave_count保持为 1,别设成 2——等两个从库 ACK 是自找死路,不是高可用,是高延迟 - 监控
Rpl_semi_sync_master_no_times和Rpl_semi_sync_master_off_times,一旦发现频繁降级,说明网络或从库 IO 真有问题,得查SHOW PROCESSLIST里从库线程状态,而不是调参数
哪些配置组合会悄悄拖垮性能
这些看似“加强可靠性”的设置,实际在生产中常成为性能黑洞。
-
rpl_semi_sync_master_wait_point = AFTER_COMMIT:主库先提交再发 binlog,主从不一致窗口变大,且无法防止主库 crash 后事务丢失;还容易和sync_binlog=1冲突,触发双刷盘 -
sync_binlog=1+innodb_flush_log_at_trx_commit=1+ 半同步:三重刷盘叠加等待,单事务延迟可能突破 10ms,尤其 SSD 负载高时 - 从库上开了
slave_parallel_workers > 0但没配slave_parallel_type=LOGICAL_CLOCK:可能导致 ACK 发送延迟不可控,因为 SQL 线程还没真正执行完就返回了 relay log 接收确认
验证半同步是否真在工作
别只看 SHOW VARIABLES LIKE 'rpl_semi_sync%' 全是 ON 就放心——那只是开关开了,不代表正在生效。
- 执行
SELECT * FROM performance_schema.replication_applier_status_by_coordinator;,检查LAST_ERROR_MESSAGE是否为空 - 查
SHOW STATUS LIKE 'Rpl_semi_sync%';,重点关注Rpl_semi_sync_master_status(是否 ON)、Rpl_semi_sync_master_yes_tx(成功半同步事务数)和Rpl_semi_sync_master_no_tx(失败回退数),二者比值持续低于 95%,说明链路不稳定 - 在主库执行
INSERT后立刻查SELECT @@global.rpl_semi_sync_master_status;,如果刚插入完就变成 OFF,大概率是rpl_semi_sync_master_timeout太小或从库挂了
真正难的不是配参数,是区分“配置生效了”和“链路稳住了”——后者得看持续几分钟的 Rpl_semi_sync_master_yes_tx 增速,而不是某次 SHOW STATUS 的快照。

