为何Hikari连接池存在大量等待连接?如何排查定位?
排查Hikari连接池耗尽问题的实用方法
从你提供的日志来看,HikariPool-1的所有10个连接都处于活跃状态,没有空闲连接,还有大量请求在等待获取连接——这典型是连接泄漏或者连接被长时间占用导致的。结合你的技术栈(Hibernate、MS SQL、Azure K8s),我整理了以下排查步骤:
1. 启用Hikari的连接泄漏检测
这是最快定位泄漏点的方法,Hikari自带了连接泄漏检测机制。你只需要在配置中添加:
spring.datasource.hikari.leak-detection-threshold=2000
(单位是毫秒,这里设置为2秒,你可以根据业务场景调整阈值)
当连接被获取后超过设定时间没有归还,Hikari会在日志中打印这个连接的调用堆栈,直接告诉你是哪段代码获取了连接但没释放。日志里会出现类似Connection leak detection triggered的标记,跟着的堆栈就是问题代码的具体位置。
2. 排查Hibernate的Session与连接管理
连接通常和Hibernate Session绑定,所以重点检查:
- 是不是手动调用了
session.openSession()但没在finally块中关闭?推荐优先使用sessionFactory.getCurrentSession()(由Spring或容器自动管理Session生命周期),避免手动管理的疏漏。 - 有没有慢查询占用连接?开启Hibernate的SQL日志,直观查看哪些SQL执行时间过长:
这样能看到完整的SQL语句和参数,快速定位没有索引的大表查询、复杂关联查询这类耗时操作——它们会让连接长时间被占用,导致池子里的连接被耗尽。logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
3. 检查K8s部署与连接池配置合理性
- 单Pod连接池大小与总连接数:如果你的应用在K8s中部署了多个Pod,每个Pod的Hikari池大小是10,那么总连接数是
Pod数量 × 10,要确保这个总数不超过MS SQL Server的最大连接数(默认是1000,可执行SELECT @@MAX_CONNECTIONS查看),同时要扣除其他应用的连接占用。 - Pod重启后的僵尸连接:K8s重启Pod时,如果应用没有优雅关闭,可能会导致MS SQL中残留未释放的僵尸连接,占用数据库资源。可以执行以下SQL清理闲置过久的连接:
SELECT * FROM sys.dm_exec_sessions WHERE status = 'sleeping' AND last_request_end_time < DATEADD(minute, -5, GETDATE())
4. 导出线程栈分析连接占用情况
在K8s的Pod中,先找到应用的Java进程ID(用ps aux | grep java),然后导出线程栈:
jstack <pid> > thread-dump.txt
打开线程栈文件,搜索HikariPool或者Connection相关的线程,查看这些线程的调用栈,找到正在占用连接的代码逻辑。比如你会看到线程卡在Hibernate的查询方法、事务提交方法,或者外部API调用上(如果事务错误地包裹了非DB操作)。
5. 从MS SQL Server端监控连接状态
直接在数据库端查看连接的详细情况,能帮你定位到具体的问题SQL:
- 查看所有Hikari相关的会话:
SELECT session_id, program_name, login_time, last_request_start_time, status FROM sys.dm_exec_sessions WHERE program_name LIKE '%Hikari%' - 查看正在执行的请求,排查阻塞或长时间运行的SQL:
这里的SELECT r.session_id, s.program_name, r.status, r.command, t.text FROM sys.dm_exec_requests r JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t WHERE s.program_name LIKE '%Hikari%'t.text就是正在执行的SQL,找到运行时间长的语句后,回到应用代码中针对性优化。
6. 检查事务边界是否合理
长事务是连接被长时间占用的常见原因:
- 检查
@Transactional注解是否被误用,比如把它加在了包含外部API调用、文件IO等耗时操作的方法上——事务会持有连接直到方法结束,非DB操作会让连接被白白占用。 - 确保所有事务都能及时提交或回滚,避免因为异常导致事务未关闭(比如try块中开启事务,finally块中没有确保提交/回滚的逻辑)。
内容的提问来源于stack exchange,提问作者ddreian
相关产品推荐
相关产品推荐

