HikariCP连接耗尽超时,MySQL大量Sleep连接问题排查求助
Spring Boot + HikariCP 连接池耗尽与Sleep连接问题排查解决
错误现象
连接池耗尽时出现如下错误:
HikariPool-1 - Connection is not available, request timed out after 30001ms (total=10, active=10, idle=0, waiting=1)
org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
执行SHOW PROCESSLIST;后发现大量Sleep状态的数据库连接:
| Id | User | Host | db | Command | Time | State | Info | Progress | |-----|----------------|----------------|----------------|---------|------|-------|------|----------| | 505 | ignosi_igjewel | localhost:48278| ignosi_igjewel1| Sleep | 545 | sleep | NULL | 0.000 | | 506 | ignosi_igjewel | localhost:48290| ignosi_igjewel1| Sleep | 556 | sleep | NULL | 0.000 | ... (and many more)
已知条件:
- Hikari连接池最大容量为10,且全部处于Sleep状态
- 依赖Spring Data JPA和Hibernate自动管理连接,未手动管理
- 新请求因等待连接超时失败
一、残留Sleep连接的成因
- 连接未被正确释放:
- 长时间运行的慢查询、未拆分的批量操作,导致连接长时间占用后转为Sleep但未归还池
- 手动获取EntityManager/JdbcTemplate时未用
try-with-resources,异常场景下未释放连接 - 事务配置不合理:超时时间过长、未正确提交/回滚,导致连接绑定在事务中无法释放
- 连接池与MySQL配置不匹配:
- HikariCP的
maxLifetime大于MySQL的wait_timeout,导致MySQL端已标记为Sleep的连接,HikariCP仍视为有效连接未回收 - MySQL的
wait_timeout设置过长,允许连接长时间处于Sleep状态
- HikariCP的
二、确保连接正确关闭/释放的方法
- 规范使用Spring Data JPA:
- Repository方法保持短周期,避免在方法内执行耗时过久的操作
- 手动使用EntityManager必须用
try-with-resources确保自动关闭:try (EntityManager em = entityManagerFactory.createEntityManager()) { // 执行数据库操作 }
- 优化事务配置:
- 非必要场景不要加
@Transactional,禁止在长时间运行的方法上绑定事务 - 合理设置事务超时:
@Transactional(timeout = 30)(单位秒),防止连接被长期占用 - 确保异常场景下事务能自动回滚(Spring默认已处理,但需避免手动捕获异常后未触发回滚)
- 非必要场景不要加
- 排查并优化慢查询:
- 用
EXPLAIN分析耗时SQL,添加合适索引或拆分大查询 - 循环中避免单条SQL执行,改用JPA的
saveAll等批量操作
- 用
三、HikariCP与MySQL的优化配置
HikariCP配置(application.yml)
spring: datasource: hikari: maximum-pool-size: 10 # 按业务需求调整,不要盲目增大 minimum-idle: 2 # 小于maximum-pool-size,减少空闲连接占用 max-lifetime: 1760000 # 必须小于MySQL的wait_timeout(例:MySQL设1800秒则此处设1760秒) connection-timeout: 30000 # 现有超时时间,可根据业务调整 idle-timeout: 600000 # 10分钟后回收空闲连接 validation-timeout: 5000 # 连接有效性检测超时 connection-test-query: SELECT 1 # MySQL下显式配置连接检测语句
MySQL配置(my.cnf/my.ini)
# 空闲连接30分钟后自动关闭 wait_timeout = 1800 interactive_timeout = 1800 # 限制MySQL最大连接数,避免资源耗尽 max_connections = 200
- 修改MySQL配置后需重启服务生效;若无法修改全局配置,可在JDBC URL添加参数:
jdbc:mysql://localhost:3306/ignosi_igjewel1?autoReconnect=true&connectTimeout=5000&socketTimeout=30000
内容的提问来源于stack exchange,提问作者RAHUL BINU
相关产品推荐
相关产品推荐

