根本原因是slave_net_timeout超时主动断连且自动重连未启用;需启用gtid+auto_position=1,合理设置slave_net_timeout(局域网60、跨机房30)、master_heartbeat_period(为前者一半)和master_connect_retry,并配置系统tcp keepalive防止中间设备断连。

MySQL主从复制频繁因网络闪断报错,根本原因不是“连不上”,而是 IO 线程在空闲时被 slave_net_timeout 主动断开,且重试机制未启用或配置不当。
Slave_IO_Running 一直 Connecting 或 No,但 telnet 通、账号正常
这大概率不是网络不通,而是连接建立后,IO 线程等不到新 binlog 数据,被 slave_net_timeout 触发主动断连。它不检测 TCP 连接是否存活,只看“有没有数据可读”。
- 检查当前值:
SHOW VARIABLES LIKE 'slave_net_timeout';(5.7.7+ 默认 60,老版本默认 3600) - 局域网稳定环境建议设为
60;跨机房或云上 VPC 建议设为30,避免抖动误判又不过度延迟故障感知 - 设太小(如
5或10)会导致主库写入空闲期稍长就频繁断连重试,加重主库握手压力 - 修改后必须执行:
STOP SLAVE IO_THREAD;+START SLAVE IO_THREAD;,仅SET GLOBAL不生效
IO 线程失败后根本不重试?先确认 GTID 和 AUTO_POSITION
MySQL 默认行为是“连一次,失败就停”。只有启用 GTID 并显式设置 AUTO_POSITION = 1,IO 线程才会在连接失败后自动重试。
- 确认 GTID 已开启:
SELECT @@gtid_mode;返回ON - 检查
CHANGE MASTER TO是否包含AUTO_POSITION = 1(不能省略,也不能是0) - 执行
SHOW SLAVE STATUS\G,确认Auto_Position字段为1;若为0,调再小的slave_net_timeout也无效 - 传统 file/pos 模式(
MASTER_LOG_FILE/MASTER_LOG_POS)下,无论怎么调参都不会自动重连
重连间隔和心跳不匹配,导致反复断连
slave_net_timeout 不是重连间隔,它只控制“读超时阈值”;真正决定重试节奏的是 MASTER_CONNECT_RETRY 和 MASTER_HEARTBEAT_PERIOD。
-
MASTER_CONNECT_RETRY控制每次重试前等待秒数,默认60;可改小(如10)缩短重试间隔:CHANGE MASTER TO MASTER_CONNECT_RETRY = 10; -
MASTER_HEARTBEAT_PERIOD(单位毫秒)是 MySQL 5.7+ 的关键心跳参数,建议设为slave_net_timeout / 2(如slave_net_timeout=30,则设MASTER_HEARTBEAT_PERIOD = 15000),否则心跳发得太晚,仍会触发超时断连 - 心跳 event 不写入 relay log,只用于维持连接活跃状态;若主库
binlog_format = STATEMENT,部分场景下心跳可能被跳过,推荐统一用ROW - 调整后同样需重启 IO 线程才生效
中间设备清空连接,光调 MySQL 参数没用
防火墙、NAT、云厂商负载均衡常默认 300 秒无流量就清空连接表项。此时即使 slave_net_timeout 设得再大,TCP 连接也早被掐断了。
- 需同步调整系统内核参数(主从两端都要设):
net.ipv4.tcp_keepalive_time = 600net.ipv4.tcp_keepalive_intvl = 60net.ipv4.tcp_keepalive_probes = 3 - 这些参数让操作系统层主动发送 TCP keepalive 包,防止中间设备误删连接
- 不配这个,所有 MySQL 层的超时与心跳优化都只是治标
最容易被忽略的一点:重连成功后 Seconds_Behind_Master 突然归零又暴涨,不是同步异常,而是 IO 线程重建连接后拉到了新位置,SQL 线程还没来得及回放——真正要盯死的是 Slave_IO_Running 和 Slave_SQL_Running 是否同时为 Yes,其余都是中间态。











