JDBC连接获取失败求助:连接池超时问题反复出现
无法获取JDBC连接池连接问题排查与解决方案
错误日志详情
11-08-2023 06:10:03.380 [ERROR] [biller-connect] com.billdesk.service.BillerConnectCRRMServiceImpl | traceId=PP012308110440256981807957132230440_fetch, bbpsTxnId=null, requestType=FETCH, billerId=BESCOM000KAR01 | message=向BOU发送响应时发生异常 org.springframework.web.client.ResourceAccessException: 对"http://xxxxx:7003/****/BillerConnectFetchResponse"发起POST请求时出现I/O错误:读取超时;嵌套异常为java.net.SocketTimeoutException: 读取超时 Caused by: java.net.SocketTimeoutException: 读取超时 11-08-2023 06:10:03.394 [ERROR] [biller-connect] org.hibernate.engine.jdbc.spi.SqlExceptionHelper | 无法获取连接,连接池错误:等待空闲对象超时 org.springframework.transaction.CannotCreateTransactionException: 无法为事务打开JPA EntityManager;嵌套异常为org.hibernate.exception.GenericJDBCException: 无法获取JDBC Connection at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.1.8.RELEASE.jar:5.1.8.RELEASE] Caused by: org.hibernate.exception.GenericJDBCException: 无法获取JDBC Connection at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final] at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final] at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final] Caused by: java.sql.SQLException: 无法获取连接,连接池错误:等待空闲对象超时 Caused by: java.util.NoSuchElementException: 等待空闲对象超时 11-08-2023 06:10:03.398 [ERROR] [biller-connect] org.hibernate.engine.jdbc.spi.SqlExceptionHelper | 无法获取连接,连接池错误:等待空闲对象超时 11-08-2023 06:10:03.398 [ERROR] [biller-connect] org.hibernate.engine.jdbc.spi.SqlExceptionHelper | 无法获取连接,连接池错误:等待空闲对象超时 11-08-2023 06:10:03.398 [ERROR] [biller-connect] org.hibernate.engine.jdbc.spi.SqlExceptionHelper | 无法获取连接,连接池错误:等待空闲对象超时 11-08-2023 06:10:03.398 [ERROR] [biller-connect] org.hibernate.engine.jdbc.spi.SqlExceptionHelper | 无法获取连接,连接池错误:等待空闲对象超时 11-08-2023 06:10:03.398 [ERROR] [biller-connect] org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler | 调用异步方法时发生意外异常:public void com.billdesk.service.BillerConnectCRRMServiceImpl.saveWorkflowStatus(java.lang.Long,java.lang.String,java.lang.String,com.billdesk.common.models.LogTrace) org.springframework.transaction.CannotCreateTransactionException: 无法为事务打开JPA EntityManager;嵌套异常为org.hibernate.exception.GenericJDBCException: 无法获取JDBC Connection Caused by: org.hibernate.exception.GenericJDBCException: 无法获取JDBC Connection at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final] at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final] at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final] Caused by: java.sql.SQLException: 无法获取连接,连接池错误:等待空闲对象超时 Caused by: java.util.NoSuchElementException: 等待空闲对象超时
问题描述
已手动清理长时间运行/不活跃的数据库会话,问题暂时缓解,但不久后再次出现无法获取JDBC Connection的报错,连接池提示等待空闲对象超时,同时伴随外部接口调用超时的情况。
排查方向
- 连接泄漏:代码中是否存在EntityManager/Connection未正确关闭的场景,尤其是异常分支
- 连接池配置:最大连接数、超时参数是否匹配业务并发需求
- 慢SQL/长事务:是否存在未优化的SQL或长时间未提交的事务,占用连接不释放
- 外部依赖影响:外部接口调用超时是否导致事务挂起,持续占用连接资源
解决方案
1. 定位并修复连接泄漏
- 开启连接池泄漏检测:以HikariCP为例,添加配置
spring.datasource.hikari.leakDetectionThreshold=3000,超过3秒未释放的连接会被记录日志,定位对应的代码位置 - 强制使用try-with-resources管理资源:所有数据库操作的EntityManager/Connection必须在try块中声明,确保自动关闭,示例:
try (EntityManager em = entityManagerFactory.createEntityManager()) { // 数据库操作逻辑 }
2. 调优连接池参数
- 调整最大连接数:根据数据库支持的最大连接数和业务并发量设置
maximumPoolSize,避免过大导致数据库负载过高,过小导致连接不足 - 优化超时参数:
- 设置
connectionTimeout=3000,缩短连接等待时间,快速失败避免线程阻塞 - 设置
idleTimeout=60000,自动回收闲置超过1分钟的连接 - 设置
maxLifetime=1800000,定期替换旧连接,避免数据库主动断开连接
- 设置
3. 处理慢SQL与长事务
- 开启数据库慢查询日志,捕捉执行时间超过1秒的SQL,通过添加索引、简化查询逻辑优化
- 收缩事务边界:将外部接口调用(如向BOU发送响应)移出数据库事务,避免事务因外部依赖超时长时间持有连接
4. 优化外部依赖容错
- 为外部接口调用添加超时与重试:使用
RestTemplate时设置connectTimeout和readTimeout,结合重试机制避免单次超时影响 - 引入断路器:使用Resilience4j等框架实现熔断,当外部服务不可用时快速失败,避免线程挂起占用连接
内容的提问来源于stack exchange,提问作者Rajib
相关产品推荐
相关产品推荐

