MySQL迁移中断主因是服务端主动断连,需客户端与服务端协同配置keepalive及连接池探活机制,并在主从同步延迟归零后切流。

MySQL 迁移期间连接中断的典型表现
迁移过程中应用突然报 Lost connection to MySQL server during query 或 MySQL server has gone away,不是网络断了,而是连接被服务端主动踢掉——常见于 mysqld 重启、主从切换、或连接空闲超时未重连。
keepalive 配置必须在客户端和服务端同时生效
只改客户端 wait_timeout 或只调大服务端 interactive_timeout 都没用。两者要协同:
- 服务端(
my.cnf)需设wait_timeout = 28800(8 小时)、interactive_timeout = 28800,避免连接空闲 8 分钟后被 kill(默认是 28800 秒,但很多云厂商改成了 600 秒) - 客户端连接字符串里加
?keepAlive=true&keepAliveDuration=30000(Java JDBC)或connect_timeout=10&read_timeout=30&write_timeout=30(Python mysql-connector) - PHP 的
mysqli不支持 keepalive,得靠mysqli_ping()主动探测,且必须在每次查询前调用
连接池配置比超时参数更关键
迁移中真正扛压的是连接池——它决定连接是否复用、失效连接能否及时剔除:
- HikariCP 必须开
connection-test-query=SELECT 1+validation-timeout=3000,否则旧连接残留池中,一用就炸 - Druid 要设
testWhileIdle=true+timeBetweenEvictionRunsMillis=30000,不然空闲连接不会被定期探活 - Node.js 的
mysql2池需配enableKeepAlive: true, keepAliveInitialDelay: 30000,否则 TCP 层保活不触发
主从切换时连接自动重试不等于连接不丢
很多 ORM 声称“支持故障转移”,实际只是失败后换地址重连——这中间的请求仍会失败,业务层必须处理重试逻辑:
- 读写分离场景下,
SELECT可能落到刚完成切换的从库,而该从库复制延迟未追平,导致查不到刚写入的数据 - 用
maxReconnects=3参数(JDBC)只能解决网络抖动,无法绕过主从角色变更带来的权限/状态不一致 - 真正可靠的方案是:迁移窗口期关闭写入,等主从同步延迟
Seconds_Behind_Master = 0后再切流量
最常被忽略的点:连接池里的连接对象本身有生命周期,哪怕服务端保持连接,客户端池子没做探活或清空,旧连接照样在迁移后继续发包到已下线的 IP。这不是配置问题,是连接池设计缺陷。










