核心是让连接池与数据库空闲管理节奏对齐:先查wait_timeout值,再设max-lifetime或min-evictable-idle-time-millis比其小60秒;启用select 1有效性检测,避免test-on-borrow;设non-zero min-idle维持心跳;捕获sqlnontransientconnectionexception等异常并安全重试。

核心是让连接池和数据库的“空闲管理节奏”对齐,避免连接池还留着连接,数据库却已悄悄断开。
同步数据库 wait_timeout 参数
先查清 MySQL 实际的 wait_timeout 值(不是默认 8 小时,云数据库常设为 300~1800 秒):
mysql> SHOW VARIABLES LIKE 'wait_timeout';
然后确保连接池关键参数都比它小:
-
HikariCP:设置
max-lifetime≤wait_timeout - 60秒(例如数据库是 1800 秒,池中设为 1740000 毫秒即 29 分钟) -
Druid:设置
min-evictable-idle-time-millis≤wait_timeout × 1000 - 60000,同时time-between-eviction-runs-millis设为 30000~60000(30~60 秒) - 务必同步设置
interactive_timeout和wait_timeout,否则可能不生效
开启连接有效性检测
光靠时间对齐还不够,要让连接池在取连接前或空闲时主动“摸一下”是否还活着:
-
HikariCP:启用
connection-test-query=SELECT 1(MySQL),并配validation-timeout=3000(3 秒防卡死) -
Druid:设
test-while-idle=true+validation-query=SELECT 1,再配合上面的驱逐周期 - 注意:不要用
test-on-borrow(每次取都查),高并发下开销大;优先用test-while-idle或 Hikari 的keepalive-time
保持最小活跃连接量
让一部分连接始终处于“被使用状态”,自然绕过空闲超时:
- 设
min-idle(Druid)或minimum-idle(Hikari)为非零值,建议为max-pool-size的 1/3 左右 - 这些常驻连接会被定期用于心跳检测(如 Hikari 的 keepalive-time 默认每 30 秒发一次 SELECT 1)
- 避免 min-idle = 0,否则低峰期所有连接都被回收,第二天首请求必报错
捕获并安全处理断连异常
即使配置到位,网络抖动或数据库重启仍可能导致瞬时断连。代码层需兜底:
- 统一拦截
SQLNonTransientConnectionException和CommunicationsException - 立即关闭当前 connection(调用
close()是安全的),再重试获取新连接 - 避免在已断开连接上调用
commit()、rollback()或任何 SQL - DAO 层或模板方法中封装重试逻辑,控制重试次数(如最多 1 次)和幂等性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











