Java技术求助:HikariPool连接耗尽导致无法获取JDBC连接
高负载下MSSQL连接耗尽问题排查与解决
可能忽略的关键问题点
1. 异常路径下的资源未正确释放
不管是EntityManager还是Connection,必须确保在所有路径(包括异常)下执行关闭操作,很多连接泄漏都是因为只在正常流程调用close(),异常时跳过了这一步:
- 对于EntityManager,推荐用try-with-resources自动管理资源:
try (EntityManager em = entityManagerFactory.createEntityManager()) { // 执行nativeQuery或存储过程逻辑 em.createNativeQuery("SELECT * FROM table").getResultList(); } // 自动调用em.close(),无论是否抛出异常 - 对于批量插入的Connection,同样强制用try-with-resources包裹:
try (Connection conn = dataSource.getConnection()) { SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(conn); // 执行批量插入操作 bulkCopy.writeToServer(dataTable); conn.commit(); } catch (SQLException e) { if (conn != null) { conn.rollback(); } // 异常处理逻辑 }
如果不用try-with-resources,一定要把close()放在finally块中,避免异常时资源泄漏。
2. Hikari连接池配置不合理
- maxPoolSize过小:高负载下连接池最大连接数不足以支撑并发请求,导致新请求等待超时。需要根据业务并发量调整该值,同时要兼顾MSSQL数据库能承受的总连接数上限。
- 连接生命周期参数配置不当:比如
idleTimeout太长导致空闲连接长期占用资源,maxLifetime未设置导致连接长期不被回收,都会加剧连接紧张的情况。 - 开启Hikari的DEBUG日志,查看连接的获取、释放明细,定位是否有连接被长时间占用未释放:
在日志配置中添加:logging.level.com.zaxxer.hikari=DEBUG
3. MSSQL用户级连接数限制
你的怀疑是合理的,MSSQL支持对单个数据库用户设置连接数上限(默认无限制,但可能被手动修改)。可以通过以下SQL查询当前各用户的连接数:
SELECT login_name, COUNT(session_id) AS connection_count FROM sys.dm_exec_sessions WHERE is_user_process = 1 GROUP BY login_name;
如果应用所用的数据库用户连接数已接近或达到上限,需要:
- 修改该用户的
MAX_CONNECTIONS参数,或调整数据库全局的max server connections配置; - 优化应用的连接使用逻辑,减少不必要的连接占用时长。
4. 事务未正确提交/回滚导致连接占用
如果使用EntityManager时开启了事务,但未正确提交或回滚,连接会被长期占用:
- 比如执行完操作后忘记提交事务,或异常时未回滚,导致连接一直处于活跃状态无法复用:
try (EntityManager em = entityManagerFactory.createEntityManager()) { em.getTransaction().begin(); // 执行数据库操作 em.getTransaction().commit(); // 确保正常流程提交 } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); // 异常时必须回滚 } // 异常处理 }
5. EntityManager与Connection的绑定泄漏
如果手动从EntityManager中获取底层Connection(比如em.unwrap(Connection.class)),但未正确处理,可能导致连接与EntityManager的绑定关系异常,即使关闭EntityManager,连接也无法回到连接池。这种情况下,必须确保手动获取的Connection也被正确关闭,或尽量避免直接操作底层Connection。
内容的提问来源于stack exchange,提问作者martin
相关产品推荐
相关产品推荐

