hikari 数据库连接池满了怎么排查 Hikari - Connection is not available, request timed out after XX ms.

问题现象

日志出现如下关键信息:

Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:48)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:109)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:136)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:254)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:262)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:236)
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:86)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:184)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:402)
… 38 common frames omitted
Caused by: java.sql.SQLTransientConnectionException: Hikari - Connection is not available, request timed out after 30000ms.
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:695)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:197)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:162)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128)
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
at org.hibernate.internal.NonContextualJdbcConnectionAccess.obtainConnection(NonContextualJdbcConnectionAccess.java:35)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:106)
… 45 common frames omitted

如果配置了相关监控,
很有可能会发现激活连接数(Hikari.pool.ActiveConnections)等于或者接近于最大连接数(Hikari.pool.MaxConnections)

在这里插入图片描述

问题分析

根据以上信息,基本可以确定是由于数据库连接池中活跃连接太多,无法获取新的连接,超过了了指定的超时时间后报错。

如果你的系统访问并发并不大,使用jstack命令打印线程信息发现也没有线程处于数据库操作的状态,则很有可能是某一处代码获取连接后没有及时释放导致。

那么如何定位是哪里的代码导致的呢?

可以使用hikari提供的泄漏检测功能,配置如下参数:

spring.datasource.hikari.leak-detection-threshold=10000

添加该参数后,如果某个线程没有释放连接,在获取连接 10000 毫秒后,系统会以WARN级别打印线程堆栈,而且不影响主程序运行。可以准确判断是哪一处代码引起,如下所示:

在这里插入图片描述

该配置会有一定的性能损耗,问题排查解决后建议关闭配置

参考

聊聊hikari连接池的leakDetectionThreshold

What constitutes an “Active” connnection? #862

<think>好的,我现在需要解决用户在Spring Boot中使用HikariCP连接池时出现的无法获取JDBC连接的问题,错误是org.springframework.jdbc.CannotGetJdbcConnectionException,提示连接不可用,请求超时。用户之前尝试过调整事务管理、修改配置,但问题依旧存在。我需要根据提供的引用和常见解决方案来分析可能的原因和解决方法。 首先,引用[2]提到HikariCP默认的连接池大小是minimumIdle=10和maximumPoolSize=10,如果并发量高,可能导致连接不足,超时获取不到连接。用户处理一万多条数据,可能并发或批量操作导致连接不够,所以需要调整连接池配置,比如增大maximumPoolSize。 引用[3]指出用户可能只配置了基本的数据源属性,没有设置其他连接池参数,比如连接超时时间、空闲时间等。默认的等待时间可能不够,或者连接因为数据库的wait_timeout设置而被关闭,导致连接泄漏。 接下来,可能的解决方案包括: 1. 调整连接池参数:增加最大连接数,设置合适的minimumIdle,调整连接超时时间(connectionTimeout),可能还要配置idleTimeout和maxLifetime,避免数据库断开连接。比如maximumPoolSize设为20,connectionTimeout延长到60秒。 2. 检查数据库的wait_timeout设置,MySQL默认是8小时,如果连接在空闲时超过这个时间会被断开。所以可能需要降低maxLifetime,使其小于数据库的wait_timeout,或者定期测试连接的有效性,配置testQuery如SELECT 1。 3. 检查是否存在连接泄漏,比如未正确关闭数据库连接。使用HikariCP的leakDetectionThreshold参数来检测泄漏,设置一个合理的阈值,比如60秒,帮助定位未关闭的连接。 4. 确保多数据源配置正确,尤其是当用户使用多数据源时,每个数据源的连接池参数都需要单独配置,避免配置冲突或遗漏。比如在配置文件中正确指定每个数据源的jdbc-url、username等,并正确初始化。 5. 其他优化措施,比如分页处理大数据量,避免一次性处理过多数据导致连接长时间占用;使用只读事务或调整事务隔离级别,减少资源占用。 需要验证用户的配置是否正确,尤其是多数据源的情况下,是否每个数据源都有独立的配置,并且没有遗漏属性。同时,查看日志是否有泄漏警告或连接获取失败的具体原因,帮助进一步诊断问题。 最后,可能需要结合多个措施,如调整连接池大小、优化SQL和事务、处理连接泄漏,以及正确配置多数据源,才能彻底解决问题。</think>在Spring Boot中解决HikariCP连接池无法获取JDBC连接的问题,需从以下方面逐步排查和优化: --- ### 一、核心问题定位 错误`HikariPool Connection not available`表明连接池资源耗尽,可能原因包括: 1. 连接池配置过小(默认`maximumPoolSize=10`) 2. 数据库连接被提前断开(MySQL默认`wait_timeout=28800秒`) 3. 存在连接泄漏(未正确释放连接) 4. 多数据源配置错误[^1] --- ### 二、配置优化方案 #### 1. 调整连接池参数 在`application.yml`中显式配置关键参数: ```yaml spring: datasource: hikari: maximum-pool-size: 20 # 根据并发量调整 minimum-idle: 5 # 最小空闲连接 connection-timeout: 60000 # 获取连接超时时间(毫秒) idle-timeout: 600000 # 空闲连接最大存活时间(需小于数据库wait_timeout) max-lifetime: 1800000 # 连接最大生命周期(建议小于数据库wait_timeout) leak-detection-threshold: 60000 # 连接泄漏检测阈值(毫秒) ``` #### 2. 数据库层优化 - 检查MySQL的`wait_timeout`参数: ```sql SHOW VARIABLES LIKE 'wait_timeout'; -- 默认28800秒(8小时) ``` 建议设置`max-lifetime`小于该值(例如1800秒)[^2]。 #### 3. 多数据源配置验证 确保每个数据源独立配置且属性完整: ```yaml spring: datasource: primary: jdbc-url: jdbc:mysql://... username: ... password: ... hikari: maximum-pool-size: 20 secondary: jdbc-url: jdbc:mysql://... username: ... password: ... hikari: maximum-pool-size: 20 ``` --- ### 三、代码层优化 1. **事务控制优化** - 避免在批量操作中使用`@Transactional`,改为分批次提交 - 使用`@Transactional(timeout=60)`显式设置事务超时 2. **连接泄漏排查** - 启用HikariCP泄漏检测日志: ```yaml spring.datasource.hikari.leak-detection-threshold=60000 ``` - 检查是否有未关闭的`ResultSet`、`Statement`或`Connection` 3. **批量处理改进** ```java // 分页处理大数据量 int pageSize = 1000; for (int i = 0; i < total; i += pageSize) { List<Data> batch = repository.findBatch(i, pageSize); processAndSave(batch); } ``` --- ### 四、验证方案 1. 监控连接池状态: ```java HikariDataSource ds = (HikariDataSource)dataSource; System.out.println("活跃连接:" + ds.getHikariPoolMXBean().getActiveConnections()); System.out.println("空闲连接:" + ds.getHikariPoolMXBean().getIdleConnections()); ``` 2. 启用HikariCP日志: ```yaml logging.level.com.zaxxer.hikari=DEBUG ``` --- ### 五、典型错误排查表 | 现象 | 可能原因 | 解决方案 | |------|---------|---------| | 高峰时段报错 | 连接池不足 | 增大`maximum-pool-size` | | 长时间空闲后报错 | 数据库断开连接 | 设置`test-query: SELECT 1` | | 随机报错 | 连接泄漏 | 启用`leak-detection-threshold` | ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值