必须同步配置mysql的wait_timeout与interactive_timeout并设为相同值,且hikaricp的max-lifetime须比其小60秒,同时启用connection-test-query=select 1和test-while-idle=true。

别只改 wait_timeout,它只是半截问题——真正要命的是连接池没跟上节奏。
查清楚你实际被哪个 timeout 控制
JDBC 连接默认走 wait_timeout,但部分驱动或连接池会带 CLIENT_INTERACTIVE 标志,结果受 interactive_timeout 管。光看文档默认值没用,得进库查:
SHOW VARIABLES LIKE 'wait_timeout';SHOW VARIABLES LIKE 'interactive_timeout';
两个值不一致?说明客户端类型识别有偏差。生产环境必须在 my.cnf 的 [mysqld] 段落里显式设成一样,比如都设为 3600(1 小时),避免隐式切换。
HikariCP 的 max-lifetime 必须比 wait_timeout 小
这是最容易翻车的点:MySQL 设了 wait_timeout = 3600,但 HikariCP 的 max-lifetime 也配成 3600 或更大,连接池就会把一个刚被 MySQL KILL 的连接继续发给你。不是 bug,是设计如此——池子只认自己没过期,不管数据库侧是否已关。
-
max-lifetime建议设为wait_timeout - 60(留 60 秒缓冲) - 必须配
connection-test-query=SELECT 1(MySQL 8.0+ 可用isValid()) - 生产环境开
test-while-idle=true+validation-timeout=3,别用test-on-borrow=true(每次取连接都查,延迟高) - Spring Boot 2.3+ 默认不检测连接有效性,
spring.datasource.hikari.connection-test-query必须显式写
MySQL 5.7 和 8.0 对事务中空闲计时的处理完全不同
这个差异不碰上不觉得,一碰就是凌晨三点报错:
- MySQL 5.7:
BEGIN后没提交,wait_timeout计时暂停;提交/回滚后才重新倒数 - MySQL 8.0:事务中只要没执行任何语句(包括
COMMIT),倒计时照常走 —— “卡在事务里” 的连接更容易被误杀
所以升级到 8.0 后,如果发现原来没问题的长事务场景开始断连,先检查是不是事务没及时结束,而不是急着调大 wait_timeout。
别信 autoReconnect=true,它早废了
MySQL 官方明确废弃该参数,5.5+ 版本开启后不会自动重连,只会让异常更难排查:
- 前一条 SQL 已提交,重连后下一条在新会话执行 → 事务断裂
- 会话级变量、预编译语句、锁全部丢失
- 日志里看到
Communications link failure,其实是它在静默抛异常,不是真重连了
真要容错,靠连接池的健康检查 + 应用层幂等/重试,而不是指望驱动“偷偷帮你续上”。
最麻烦的从来不是改哪个数字,而是服务端、连接池、应用代码三层生命周期没对齐——wait_timeout 是底线,max-lifetime 是保险绳,而 close() 调用和事务边界才是最后一道闸。











