HikariCP报连接超时根本原因是活跃连接长期≥最大连接数且新请求排队超时,常见于慢查询、事务未提交、连接泄漏或maximumPoolSize过小;需结合监控、日志、SQL分析和合理参数配置综合排查。

为什么 HikariCP 报 Connection is not available, request timed out after 30000ms
这不是数据库挂了,而是连接池彻底没连接可用了。根本原因是:活跃连接数长期 ≥ 最大连接数(maximumPoolSize),且新请求排队超时。常见于慢查询堆积、事务未及时提交、连接泄漏,或 maximumPoolSize 设得太小。
实操建议:
- 先查当前活跃连接:
SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep';,确认是否真有大量长事务或卡住的查询 - 检查应用日志里是否有未关闭的
Connection、Statement或ResultSet—— 尤其在异常分支里漏掉close() -
HikariCP默认不自动回收泄漏连接,需显式开启:leakDetectionThreshold=60000(单位毫秒),设太低会误报,太高起不到作用 - 别盲目调大
maximumPoolSize:MySQL 默认max_connections=151,超过会直接拒绝新连接;Java 端线程数也会上涨,可能触发 GC 压力
maximumPoolSize 和 minimumIdle 怎么设才不翻车
这两个值不是拍脑袋定的。设高了压垮 DB,设低了并发一上来就排队;设太低的 minimumIdle 会导致连接频繁创建销毁,增加握手开销。
实操建议:
- 先估算业务峰值 QPS 和平均响应时间(比如 200 QPS × 0.2s = 40 并发连接需求),再留 20%~30% 余量 →
maximumPoolSize初值可设为 50~60 -
minimumIdle建议设为maximumPoolSize的 70%~100%,避免流量突增时疯狂建连;但若 DB 实例资源紧张,可降到 50%,靠connectionTimeout控制等待 - 注意 MySQL 的
wait_timeout(默认 28800 秒)和HikariCP的idleTimeout(默认 600000ms)要错开,否则空闲连接可能被 DB 主动断开,而池子还傻等它“健康” - 启用
testOnBorrow=false(默认),改用connectionTestQuery=SELECT 1+validationTimeout=3000,更轻量
Spring Boot 里怎么验证连接池真在按预期工作
光看配置文件不等于生效。很多项目配了 maximumPoolSize,结果启动日志里显示的仍是默认值 10 —— 因为属性名写错、配置没加 spring.datasource.hikari. 前缀,或者被其他 auto-configuration 覆盖了。
实操建议:
- 启动时搜日志关键词:
HikariPool-1 - Starting...后面跟着的maximumPoolSize和minimumIdle值,才是最终生效值 - 运行时访问 Actuator 的
/actuator/metrics/hikaricp.connections.active(需暴露端点),实时看活跃连接数曲线,比埋点更直接 - 用
jstack抓线程栈,搜HikariPool相关线程阻塞点,能定位是卡在获取连接,还是卡在执行 SQL - 别信 “配置 reload”:Spring Boot 的
@ConfigurationProperties不支持运行时热更新连接池参数,改完必须重启
连接池耗尽后,SQL 执行失败是抛 SQLException 还是 RuntimeException
是 java.sql.SQLTimeoutException,它继承自 SQLException,不是 RuntimeException。这意味着:如果你用的是 Spring 的 JdbcTemplate,它会自动包装成 DataAccessException(运行时异常);但原生 JDBC 调用里,必须显式 catch SQLException,否则编译不过。
实操建议:
- 原生 JDBC 场景下,一定要
catch (SQLException e),并判断e instanceof SQLTimeoutException,而不是只捕获Exception - Spring 项目中,
DataAccessException子类如CannotGetJdbcConnectionException才对应连接获取失败,它不包含 SQL 执行超时 —— 后者仍是UncategorizedSQLException包裹的原始SQLTimeoutException - 监控告警时,别只盯
SQLException总量:要单独提取SQLTimeoutException和CommunicationsException(连接断开)做区分,前者调参,后者查网络或 DB 状态
连接池调优最麻烦的从来不是数字本身,而是把“连接生命周期”真正串进整个请求链路里——从 HTTP 入口、Service 事务边界、到 DAO 层 close 时机,漏掉一环,前面所有参数都白调。


















