排查Spring Web应用中Hikari连接池的数据库连接泄漏问题
排查Spring Web应用Hikari连接池泄漏的实用方法
我之前维护Spring Web应用时碰到过完全一样的问题——周期性出现连接池耗尽、获取连接超时,十有八九是连接泄漏(也就是获取了数据库连接但没有正确释放)导致的。下面是我亲测有效的排查步骤,一步步帮你定位问题:
1. 让Hikari主动“举报”泄漏点
Hikari本身自带连接泄漏检测功能,开启后能直接帮你定位代码问题:
- 在
application.properties(或application.yml)里添加这些配置:
开启后,Hikari检测到泄漏时会打印完整的堆栈跟踪,顺着堆栈就能找到哪段代码拿了连接没归还。# 超过30秒未释放连接就触发泄漏日志,可根据业务调整时长 spring.datasource.hikari.leak-detection-threshold=30000 spring.datasource.hikari.log-leaked-connections=true # 开启Hikari DEBUG日志,方便追踪连接的获取/释放流程 logging.level.com.zaxxer.hikari=DEBUG
2. 检查代码中的连接释放逻辑
连接泄漏最常见的原因就是代码没正确释放连接,重点排查这几个场景:
- 手动获取连接的代码:如果有用
dataSource.getConnection()手动拿连接的情况,必须用try-with-resources自动关闭,比如:
绝对不要手动调用try (Connection conn = dataSource.getConnection()) { // 执行数据库操作 } catch (SQLException e) { // 异常处理 }conn.close()却在异常分支漏处理,try-with-resources是最稳妥的方式。 - JPA/Hibernate事务管理:如果用了
@Transactional,要注意:- 不要在事务方法里手动获取连接,Spring会自动管理连接生命周期,手动操作很容易导致双重占用或泄漏。
- 检查事务范围是否过大——比如把远程调用、文件IO这类耗时操作放到事务里,会导致连接被长时间占用,最终耗尽池内资源。
- 异常分支的连接释放:有些代码在正常路径关了连接,但异常路径没处理,比如:
这种情况用Connection conn = null; try { conn = dataSource.getConnection(); // 数据库操作 } catch (SQLException e) { // 只处理异常,没关连接! } finally { // 这里必须确保关闭连接 if (conn != null) { try { conn.close(); } catch (SQLException e) { // 记录日志即可 } } }try-with-resources就能彻底避免。
3. 从数据库层面排查连接状态
光看应用日志不够时,直接去数据库看连接的实际状态:
- 以MySQL为例,登录数据库后执行:
重点看SHOW PROCESSLIST;Command列为Sleep且Time列数值很大的连接——这些就是长时间未释放的连接。如果大量这类连接都是你的应用创建的,基本可以实锤是泄漏了。 - 也可以用精确查询过滤你的应用连接:
这样能清晰看到应用占用的连接数量和状态。SELECT * FROM information_schema.processlist WHERE USER = '你的数据库用户名' AND HOST LIKE '%你的应用服务器IP%';
4. 用监控工具实时查看连接池状态
如果是Spring Boot应用,用Actuator能快速获取连接池实时状态:
- 先引入Actuator依赖(Maven为例):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> - 在配置里开启HikariCP端点:
management.endpoints.web.exposure.include=hikaricp - 访问
http://你的应用地址/actuator/hikaricp,就能看到activeConnections(活跃连接数)、idleConnections(空闲连接数)、pendingConnections(等待队列长度)等关键指标。故障发生时如果activeConnections等于maximum-pool-size且pendingConnections持续增长,说明连接已被耗尽。
如果没用Actuator,也可以手动注入HikariDataSource,通过getHikariPoolMXBean()获取监控数据,写个简单接口打印出来方便排查。
最后验证修复效果
找到泄漏点修复后,一定要验证:重启应用后观察连接池活跃连接数是否稳定(不会持续增长),同时监控日志确保不再出现连接超时报错。
内容的提问来源于stack exchange,提问作者Thomas Feiler
相关产品推荐
相关产品推荐

