仅调 wait_timeout 和 interactive_timeout 无法彻底解决“僵尸连接”,因连接池未同步淘汰已失效连接;需配合 connect_timeout 设置及连接池 maxLifetime 等参数协同生效。

只改 wait_timeout 和 interactive_timeout 不足以自动回收“僵尸连接”——它们只能让 MySQL 主动断开空闲连接,但应用层连接池若没同步退役这些连接,下一次取用时照样报 MySQL server has gone away。
为什么改了参数还是有 Sleep 连接不消失?
常见现象:配置文件写了 wait_timeout = 600,重启 MySQL 后跑 SHOW PROCESSLIST;,仍看到大量 State = 'Sleep' 且 Time > 600 的连接。
- 配置没真正生效:只改了
my.ini却忘了重启服务;或用了SET GLOBAL wait_timeout = 600但权限不足/未用SET PERSIST持久化 - 连接正处在事务中:
wait_timeout只对空闲连接起作用,一旦有未提交/回滚的事务,计时暂停 - 客户端保活干扰:JDBC 的
autoReconnect=true会让驱动在底层 TCP 断开后尝试重连,掩盖真实状态,MySQL 却已将其标记为关闭 - 连接池“假活”:HikariCP 或 Druid 没设
maxLifetime,连接被复用后长期滞留池中,MySQL 已 kill,池子还当它可用
必须同步设置的三个 MySQL 参数
这三个值要一起调,不能只动一个:
-
wait_timeout = 600:控制 JDBC 等非交互式连接空闲 10 分钟断开(生产建议 600~1800,别低于 300) -
interactive_timeout = 600:命令行、Navicat 等交互式工具也按同样策略清理,避免开发连着不关堆积 -
connect_timeout = 10:限制 TCP 握手+认证阶段最长等待时间,防慢网或扫描拖住线程;设太高(如 60)反而积压无效连接请求
net_read_timeout 和 net_write_timeout 影响的是查询执行中的读写卡顿容忍度,和“僵尸连接”无关,先不动。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
HikariCP 必须配 maxLifetime 对齐 MySQL 超时
MySQL 断连接只是第一步,关键在连接池得“提前退休”——否则拿到一个已被 MySQL 关闭的连接,一用就崩。
- HikariCP:设
maxLifetime=540000(9 分钟),比wait_timeout=600少至少 60 秒,留出网络延迟和状态同步缓冲 - Druid:对应参数是
maxEvictableIdleTimeMillis,同样建议设为wait_timeout * 1000 - 60000 - 别依赖
testOnBorrow或validationQuery:每次取连接都查库(如SELECT 1),QPS 高时开销爆炸;优先用connectionInitSql=SELECT 1+keepaliveTime做轻量心跳
怎么验证配置真生效了?
别只信配置文件或 SHOW VARIABLES,要看运行时行为:
- 跑
SHOW PROCESSLIST;,筛选State = 'Sleep'且Time > 600的行:如果还有,说明参数没生效,或连接卡在事务里 - 查
SHOW VARIABLES LIKE '%timeout%';,确认wait_timeout和interactive_timeout确实是你要的值(注意拼写:interac是截断显示,不是错字) - 检查连接池日志:HikariCP 开启
debug日志后,能看到连接被evict或close的记录,确认maxLifetime是否触发
最容易被忽略的一点:Windows 下防火墙或安全软件可能在连接空闲时主动发 RST,导致连接在到达 MySQL 超时前就被掐断——这种属于 TCP 层断连,wait_timeout 根本不参与,得从网络设备侧排查。

















