MySQL主从复制断开后不会自动持续重连,默认仅首次尝试;需调小slave_net_timeout(建议10~30秒)并重启IO线程,配合MASTER_CONNECT_RETRY和MASTER_RETRY_COUNT参数及监控才能实现快速、可靠重连。

主从复制断开后,MySQL 会不会自动重连
会,但默认行为非常保守:只在 CHANGE MASTER TO 后首次启动时尝试一次连接,失败就停在 Slave_IO_Running: No,不会持续重试。
真正起作用的是 MASTER_RETRY_COUNT 和 MASTER_CONNECT_RETRY 这两个参数,它们控制 IO 线程在连接失败后的重试逻辑,但很多人误以为只要开了 relay_log_recovery=ON 或启用了 GTID 就能“自动恢复”,其实不是。
-
MASTER_RETRY_COUNT默认是 86400(24 小时),但这个值只有在连接被明确拒绝(比如端口不通、认证失败)时才生效;如果网络只是暂时中断(TCP 连接已建立但后续包丢弃),MySQL 可能卡在 “reading event” 状态,根本不会触发重试逻辑 -
MASTER_CONNECT_RETRY默认是 60 秒,即每次重试前等待的时间,不是超时时间——连接建立超时由slave_net_timeout控制,它默认是 3600 秒(1 小时),这才是导致“断了等很久才重连”的元凶 - GTID 模式下,即使重连成功,如果主库的 binlog 已被清理,从库仍会报错
Could not find first log file name in binary log index file,此时光靠重试没用,得人工干预
如何让 IO 线程更快感知并重连
核心是缩短 slave_net_timeout,它决定了 IO 线程在收不到主库数据时,多久判定为“网络异常”并主动断开当前连接、进入重试流程。
这个参数必须在从库上动态设置,并重启 IO 线程才生效:
SET GLOBAL slave_net_timeout = 30; STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
- 设太小(如
5)可能导致误判:主库写入空闲期稍长就会频繁断连重试,增加握手开销 - 设太大(如默认
3600)会导致抖动后长达一小时无响应,复制延迟飙升且不报警 - 生产建议值:10~30 秒,配合监控(比如定期查
Seconds_Behind_Master和Slave_IO_Running)可平衡灵敏度与稳定性
重连失败后,错误日志里常见但容易忽略的关键线索
别只盯着 ERROR 2003 (HY000) 这类连接拒绝错误。网络抖动更常表现为:
-
Got timeout reading communication packets:说明连接已建,但主库没及时发包,此时slave_net_timeout才是关键 -
Unexpected EOF found when reading file:IO 线程读到不完整事件,大概率是主库崩溃或 binlog 写了一半就挂了,需检查主库磁盘和sync_binlog设置 -
The slave I/O thread stops because a fatal error is encountered when it tries to get the value of SERVER_UUID:GTID 模式下主库 UUID 变了(比如克隆了实例但没重置),这不是网络问题,重试无效
这些错误不会触发重试计数器归零,也不会改变 Retries_since_last_failure 值,所以光看这个变量会误判“一直没重试”。
配置完重试参数,为什么还是不重连
最常踩的坑是:改了参数但没重启 IO 线程,或者改的是全局变量但客户端连接未重连。
-
slave_net_timeout是全局动态变量,但修改后必须执行STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;才生效,仅START SLAVE不够 -
MASTER_CONNECT_RETRY和MASTER_RETRY_COUNT是CHANGE MASTER TO的一部分,修改后必须显式执行该命令(哪怕只改一个参数),否则旧值继续生效 - 使用
mysqladmin ping或TCP ping检查网络层通不通,不能代替验证 MySQL 层是否真能握手成功——有些防火墙会放行 TCP SYN,但拦截后续应用层包
网络抖动本身不可控,能做的就是让 MySQL 在异常发生后尽快发现、尽快行动,而不是等它自己“想通”。参数调得再细,也抵不过一次没监控的连接中断。


















