MySQL延迟复制通过CHANGE MASTER TO MASTER_DELAY=N实现,由从库SQL线程主动sleep控制重放时间差,精确稳定;而tc/netem模拟弱网作用于网络层,仅导致I/O线程超时或断连,无法实现可控延迟。

MySQL 延迟复制(CHANGE MASTER TO ... MASTER_DELAY=N)本身不依赖网络模拟,但“弱网”是常见误读——真正影响复制延迟的是从库 SQL 线程的执行节奏,不是网络丢包或抖动。测试环境要验证延迟复制行为,直接配置 MASTER_DELAY 即可,无需引入 tc 或 netem。
为什么不用 tc/netem 模拟弱网做 MySQL 延迟复制?
MySQL 主从复制的 I/O 线程拉取 binlog 是批量、阻塞式 TCP 读,只要连接不断,弱网只会导致短暂重试或超时(报错 ERROR 2013 (HY000)),不会产生可控、稳定的“N 秒延迟”。而 MASTER_DELAY 是从库 SQL 线程主动 sleep,精确控制重放时间差,这才是生产中用于误操作回滚、审计观察的标准手段。
- tc/netem 作用于网络层,可能让 I/O 线程卡住甚至断连,触发
Seconds_Behind_Master飙升但不可控 -
MASTER_DELAY是 SQL 线程级调度,不受网络抖动干扰,Seconds_Behind_Master显示稳定 N 秒 - Fleet 测试环境(
tools/mysql-replica-testing/)默认就用MASTER_DELAY=1,靠make db-replica-setup自动注入
如何正确配置 MySQL 延迟复制(1 秒为例)
在已连通的主从环境中,只需在从库执行一条命令。注意:必须先 STOP SLAVE,且主库 binlog 必须开启、格式为 ROW。
- 确认主库状态:
SHOW MASTER STATUS,记下File和Position - 从库停复制:
STOP SLAVE - 重新指定延迟:
CHANGE MASTER TO MASTER_DELAY = 1 - 启动复制:
START SLAVE - 验证:
SHOW SLAVE STATUS\G中检查SQL_Delay: 1和Seconds_Behind_Master: 1
常见错误现象与修复
延迟复制配置后仍显示 Seconds_Behind_Master: 0 或报错,多数因基础条件缺失:
-
ERROR 3079 (HY000):从库server-id未设置或与主库重复 → 检查my.cnf并重启 MySQL -
Seconds_Behind_Master为NULL:I/O 线程未运行 → 执行START SLAVE IO_THREAD - 延迟不生效(始终为 0):从库未启用
relay_log或read_only=0→ 确保relay-log=mysql-relay-bin且read-only=1 - Fleet 启动失败提示
mysql_read_replica连接拒绝:宿主机端口映射冲突(如 3309 被占用)→ 改docker-compose.yml中ports值
延迟复制对 Fleet 读写分离的实际影响
Fleet 的 mysql_read_replica 配置只控制查询路由,不感知复制延迟。这意味着:
- 即使从库延迟 1 小时,Fleet 的 Live Query 仍会把读请求发给它,返回旧数据
- 延迟仅用于人工干预场景(如发现主库误删表,立刻停从库 SQL 线程,跳过该事件)
- 监控重点应是
Seconds_Behind_Master是否持续增长(说明 SQL 线程积压),而非是否等于MASTER_DELAY
真正需要弱网模拟的环节,其实是 Fleet server 到 MySQL 实例的连接稳定性测试,那属于应用层网络健壮性范畴,和复制机制无关。


















