结论是必须让连接池max-lifetime严格小于wait_timeout并配合有效性验证,否则仍会复用已断连接;需实查当前生效的wait_timeout和interactive_timeout值,二者须统一设置且HikariCP中max-lifetime应比wait_timeout小至少30秒,禁用autoReconnect=true,改用保活机制与连接探测。

直接说结论:不要只调大 wait_timeout,而要让连接池的生命周期严格小于它,并配合连接有效性验证——否则调再大也救不了“拿到断连还去用”的问题。
查清当前生效的 wait_timeout 和 interactive_timeout 值
别信文档默认值,不同 MySQL 版本、启动方式、甚至 JDBC 驱动版本都可能影响实际值。连接进 MySQL 后必须执行:
SHOW VARIABLES LIKE 'wait_timeout'; SHOW VARIABLES LIKE 'interactive_timeout';
注意两点:
-
wait_timeout控制非交互连接(JDBC 应用默认走这个) -
interactive_timeout控制 mysql 命令行这类交互式连接;但部分连接池(如旧版 c3p0)会显式声明CLIENT_INTERACTIVE,此时也会受它影响——所以两个都得查、都得调
HikariCP 连接池里 max-lifetime 必须小于 wait_timeout
这是最容易被跳过的硬约束。HikariCP 的 max-lifetime 是连接在池中存活的最长时间,MySQL 的 wait_timeout 是服务端允许空闲的最长时间。如果前者 ≥ 后者,连接池就会把一个已被 MySQL 主动关闭的连接再分配出去,下一次 executeQuery() 直接抛 CommunicationsException。
实操建议:
- 若 MySQL 侧设了
wait_timeout = 3600(1 小时),HikariCP 就必须设max-lifetime = 3500(留 100 秒缓冲) - 绝对不要设
max-lifetime=0(永久存活)或等于wait_timeout - Spring Boot 中配置项是
spring.datasource.hikari.max-lifetime
启用连接验证,但别滥用 test-on-borrow
每次从池里取连接都做一次 SELECT 1 验证(test-on-borrow=true)虽可靠,但会显著拖慢高并发下的获取速度。更轻量的做法是:
- 开启保活机制:
keepalive-time=30000(每 30 秒发一次SELECT 1) - 配
connection-test-query=SELECT 1(MySQL 8.0+ 推荐用isValid()) - 设
validation-timeout=3000(验证超时 3 秒,避免卡住线程)
注意:HikariCP 2.7.0+ 已弃用 test-on-borrow,改用 connection-init-sql 或保活机制更稳妥。
别碰 autoReconnect=true,它已失效且危险
MySQL 5.5+ 官方明确废弃该参数。实测开启后仍会抛 Communications link failure,且可能掩盖事务断裂风险——比如前一条 SQL 已提交,重连后下一条在新会话执行,造成逻辑不一致。
真正该做的不是让驱动“偷偷重连”,而是让连接池提前发现失效、主动剔除、按需重建。这靠的是上面三个动作的组合:错开生命周期 + 定期探测 + 拒绝超时连接。
最后提醒一句:MySQL 的 wait_timeout 是会话级固化值,SET GLOBAL 修改后只对新连接生效,旧连接仍按建连时的值倒计时——这意味着你改完参数,必须等旧连接自然退出或重启应用,才能看到效果。


















