wait_timeout是mysql主动断开闲置连接的阈值,非避免断开;需使连接池maxlifetime严格小于它,并同步配置connect_timeout等参数以协同生效。

wait_timeout 不是用来“避免”闲置连接断开的,它恰恰是控制 MySQL 主动断开闲置连接的开关。真正要让连接不被意外中断,得让它在 MySQL 杀掉之前,就被连接池主动回收,并验证有效性。
查清当前生效的 wait_timeout 值
不同环境实际值差异极大:腾讯云 RDS 常为 300 秒,MySQL 官方 Docker 镜像默认是 28800 秒,某些 phpEnv 环境甚至设成 60 秒。别信文档,直接连上去查:
- 执行
SELECT @@wait_timeout, @@interactive_timeout;—— 注意单位是秒,且两个值必须一致 - 避免用
SHOW VARIABLES LIKE '%timeout%',它默认返回会话变量;要看全局值,用SHOW GLOBAL VARIABLES LIKE 'wait_timeout' - 如果两个值不等,说明服务端行为已分裂,后续排查会绕弯子
永久修改必须写 my.cnf 并重启 mysqld
临时执行 SET GLOBAL wait_timeout = 600 只对之后新建连接生效,且 MySQL 重启即失效。生产环境必须落盘:
- 编辑
/etc/my.cnf或/etc/mysql/my.cnf(Linux/macOS),或C:\phpEnv\config\mysql\my.ini(Windows) - 只在
[mysqld]段下添加两行:wait_timeout = 600和interactive_timeout = 600 - 务必删掉
[client]段里的同名配置——那只是给mysql命令行用的,不影响服务端判定 - 改完执行
sudo systemctl restart mysql(不是reload)
HikariCP 的 maxLifetime 必须严格小于 wait_timeout
把 wait_timeout 设成 600 秒(10 分钟),但 HikariCP 的 maxLifetime 默认是 1800000 毫秒(30 分钟),连接池根本等不到 MySQL 断它,自己先销毁了;反过来,如果池子 idleTimeout 是 10 分钟,而 MySQL 设成 1 小时,那连接大概率在被 MySQL 杀之前就被池子回收了。
- 正确做法:
maxLifetime设为540000毫秒(9 分钟),比wait_timeout = 600少至少 60 秒缓冲 - 必须启用连接验证:
connection-test-query=SELECT 1(MySQL 8.0.22+ 推荐用connection-init-sql),配合test-while-idle=true和validation-timeout=3000 - 禁用
autoReconnect=true:MySQL Connector/J 5.5+ 已废弃,它不会自动重连,只会掩盖事务断裂、会话变量丢失等真实问题
别漏掉 connect_timeout 和 net_read_timeout
wait_timeout 管空闲,connect_timeout 和 net_read_timeout 管建立和传输阶段:
-
connect_timeout = 10:控制 TCP 握手和认证最长等待时间,防慢网或扫描拖住线程 -
net_read_timeout = 30和net_write_timeout = 60:影响大 BLOB 查询、批量导入或主从延迟突增时的卡顿容忍度,不是空闲超时,但若业务有长查询,需同步评估 - 这两个参数也要写进
[mysqld]段并重启才生效
最容易被忽略的是:改完 wait_timeout 后没同步调小连接池的 maxLifetime,结果 MySQL 已断开连接,池子还把它当“活连接”分配出去,下一次使用直接报 Communications link failure。参数值本身不重要,差值和协同才关键。











