数据库连接池耗尽本质是申请速度持续超过释放速度,核心在修复连接泄漏、慢SQL及不合理使用;需用try-with-resources确保Connection/Statement/ResultSet自动关闭,结合leakDetectionThreshold定位泄漏点,并合理配置池参数避免压垮数据库。

数据库连接池耗尽,本质是应用申请连接的速度持续超过连接释放(归还)的速度,导致池中无可用连接。解决重点不在“加连接数”,而在于定位并修复连接泄漏、慢SQL、同步阻塞或不合理使用模式。
检查连接是否被正确释放
最常见原因是 Connection、Statement、ResultSet 未在 finally 块或 try-with-resources 中关闭,尤其在异常路径下容易遗漏。
✅ 正确写法(推荐 try-with-resources):
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM user WHERE id = ?");
ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
// 处理结果
}
} // 自动关闭 conn、stmt、rs,无论是否异常
❌ 错误写法(可能泄漏):
Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(...); // 忘记 close(),或只在 try 内 close,异常时跳过
排查长事务与慢 SQL
一个连接被占用时间过长(如事务未提交、SQL 执行超 10s),会持续占用池资源,引发连锁等待。
- 启用数据库慢查询日志(如 MySQL 的
slow_query_log),定位执行 >1s 的 SQL - 在连接池配置中设置
maxWaitMillis(如 HikariCP 的connection-timeout),让超时请求快速失败,避免线程无限等待 - 对高频更新/复杂查询加索引,避免全表扫描;拆分大事务,减少单次事务持有连接时间
验证连接池配置是否合理
盲目调大 maximumPoolSize 可能掩盖问题,甚至压垮数据库。应结合实际负载调整:
- 观察监控指标:活跃连接数(active)、空闲连接数(idle)、等待连接的线程数(waiting)
- 典型经验值:PostgreSQL 推荐每 CPU 核心 2–4 连接;MySQL 一般不超过 50–100(需配合 max_connections 设置)
- HikariCP 推荐配置示例:
spring.datasource.hikari.maximum-pool-size=20 spring.datasource.hikari.minimum-idle=5 spring.datasource.hikari.connection-timeout=30000 spring.datasource.hikari.idle-timeout=600000 spring.datasource.hikari.max-lifetime=1800000
识别隐式连接泄漏场景
以下情况容易被忽略,但会导致连接不归还:
- Spring 中使用
@Transactional时,方法内手动调用dataSource.getConnection()却未关闭 —— Spring 管理的事务连接与手动获取的连接是两套生命周期 - 异步任务(如
@Async)中获取连接,但线程结束前未释放 - 连接被存入 ThreadLocal 且未清理(如某些自定义上下文工具类),造成“假活跃”连接
- 连接池启用了
leakDetectionThreshold(如 HikariCP 设为 60000 毫秒),可在日志中直接捕获泄漏堆栈


















