slave_net_timeout应设为60~120秒以平衡灵敏度与抗抖动能力,修改后需重启IO线程;MySQL 5.7+需主库配置MASTER_HEARTBEAT_PERIOD(建议≤60秒)并确保复制运行中,GTID模式下应以Retrieved_Gtid_Set与Executed_Gtid_Set差值判断真实延迟。

主从连接断开后频繁重连:检查 slave_net_timeout 是否过小
MySQL 从库检测主库失联,靠的是 TCP 连接空闲超时,不是心跳包。默认 slave_net_timeout 是 3600 秒(1 小时),网络抖动持续几秒就断连?那说明这个值太保守了。它决定从库在收不到任何数据时,多久主动关闭连接并尝试重连。
- 生产环境建议设为
60~120,兼顾灵敏度和抗抖动能力 - 修改后需重启 IO 线程:
STOP SLAVE IO_THREAD; START SLAVE IO_THREAD; - 注意:该参数是全局动态变量,但旧版本(如 5.6)不支持运行时修改,必须写入配置文件并重启 mysqld
MySQL 5.7+ 的真正心跳机制:MASTER_HEARTBEAT_PERIOD 怎么设才有效
5.7 引入了基于 binlog event 的心跳(HEARTBEAT event),但必须由主库主动发、从库被动收——它不替代 TCP 层检测,而是让从库更早感知主库“活着但没新事件”。关键在主库配置 CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD = N,单位是秒,且必须 N 才起作用。
- 典型值设
10或15,比slave_net_timeout小至少 10 秒 - 执行后需重启 IO 线程,否则不生效;心跳 event 不会写入 relay log,只用于维持连接状态
- 如果主库
binlog_format = STATEMENT,某些场景下心跳可能被跳过,推荐统一用ROW
网络层干扰导致的假断连:别忽略 tcp_keepalive 系统参数
MySQL 自身不控制底层 TCP keepalive 行为。当中间有防火墙、NAT 设备或云厂商负载均衡时,它们常默认 300 秒无流量就清空连接表项。此时即使 MySQL 的 slave_net_timeout 设得再大也没用——连接早被中间设备掐断了。
- Linux 上检查:
sysctl net.ipv4.tcp_keepalive_time(默认 7200),建议调低至600 - 配套调整:
net.ipv4.tcp_keepalive_intvl = 60,net.ipv4.tcp_keepalive_probes = 3 - 这些内核参数需在主从两端同时设置,仅改 MySQL 配置治标不治本
误判“同步延迟”:用 Seconds_Behind_Master 判断前先看 Slave_IO_Running 和 Slave_SQL_Running
网络抖动恢复后,Seconds_Behind_Master 可能短暂飙高,但这不等于同步异常。真正要盯的是两个线程状态。一旦 Slave_IO_Running 变成 No,说明 IO 线程已断连重试中;若 Seconds_Behind_Master 为 NULL,大概率是 IO 线程没跑起来,而不是 SQL 慢。
- 监控脚本里不能只告警
Seconds_Behind_Master > 60,必须加条件:Slave_IO_Running = Yes AND Slave_SQL_Running = Yes -
SHOW SLAVE STATUS中的Retrieved_Gtid_Set和Executed_Gtid_Set差值更能反映真实追赶进度,尤其在 GTID 模式下 - 频繁断连时,
Seconds_Behind_Master会反复归零又跳升,这种毛刺本身是网络问题信号,不是复制逻辑缺陷
心跳周期和 TCP keepalive 是两层事,一个在应用协议层,一个在传输层,漏掉哪一层都可能让抖动变成故障。配完记得用 tcpdump 抓包确认心跳 event 真实发出,而不是只信 SHOW SLAVE STATUS 里的字段。


















