主从连接超时中断的典型现象是Slave_IO_Running: No且Seconds_Behind_Master: NULL,Last_IO_Error显示连接超时;slave_net_timeout控制IO线程保活,net_read_timeout影响单次读操作,二者不可混淆。

主从连接超时中断的典型现象
MySQL 5.7 主从复制因网络抖动中断时,SHOW SLAVE STATUS\G 中最直接的信号是:Slave_IO_Running: No,且 Seconds_Behind_Master: NULL,Last_IO_Error 通常显示类似:error connecting to master 'repl@10.0.2.100:3306' - retry-time: 60 retries: 1 或更明确的 Lost connection to MySQL server at 'reading authorization packet', system error: 110(ETIMEDOUT)。这不是 SQL 执行错误,而是 TCP 层连接被重置或未及时响应。
slave_net_timeout 和 net_read_timeout 的实际作用差异
这两个参数常被混淆,但职责完全不同:slave_net_timeout 控制 IO 线程在收不到主库任何数据(包括心跳、binlog event、even空包)时的等待上限,超时后主动断开并重连;而 net_read_timeout 是通用会话级参数,影响的是当前连接上单次读操作的阻塞时限(比如执行一条慢查询时),对复制 IO 线程的保活无直接影响。
排查时重点确认:
-
slave_net_timeout值是否过小(默认 3600 秒),在高延迟、偶发丢包的跨机房链路中建议设为 60–120 秒 - 该参数修改后需重启 IO 线程生效:
STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;,仅STOP/START SLAVE不够 -
net_read_timeout可适当调大(如 120),但不能替代slave_net_timeout解决抖动重连问题
用 tcpdump 验证真实网络行为
日志里看到 “retry-time: 60” 不代表网络真卡了 60 秒——MySQL 的重试逻辑受多个定时器叠加影响。要确认是否为真实丢包或 RST,必须抓包比对时间点:
- 在从库执行:
tcpdump -i any -w slave_io.pcap host <master_ip> and port 3306</master_ip> - 复现一次中断后,用 Wireshark 打开 pcap,过滤
tcp.flags.reset == 1 or tcp.len == 0 - 重点看:主库是否发了
ACK后长时间无数据(说明主库写阻塞)、从库是否发了FIN/RST(说明本地内核主动断链)、是否存在连续重传(TCP Retransmission)
如果抓包显示从库在超时前就发了 RST,那问题大概率出在本地防火墙、中间设备策略或 net.ipv4.tcp_fin_timeout 内核参数过激回收连接。
启用半同步 + 心跳包降低误判率
纯异步复制下,IO 线程只能靠收数据判断主库存活,网络抖动极易触发假中断。MySQL 5.7 原生支持半同步(需安装插件),配合 rpl_semi_sync_master_timeout 和心跳机制可显著改善:
- 开启半同步后,主库在 commit 前会等待至少一个从库 ACK,这本身就能暴露链路质量;若超时,错误记入
error log而非静默断连 - 即使不强制半同步,也可通过
CHANGE MASTER TO ... MASTER_HEARTBEAT_PERIOD = 5.0启用心跳(单位秒),让主库每 5 秒发一个空 event,缩短slave_net_timeout检测窗口 - 注意:
MASTER_HEARTBEAT_PERIOD必须小于slave_net_timeout,否则心跳无效
网络抖动本身难以根治,但把“连接断了”和“只是暂时没收到数据”区分开,才是排查起点。很多 case 的本质不是 MySQL 复制坏了,而是你没告诉它:这条链路本来就不稳,别那么快放弃。


















