【Java踩坑笔记】42_数据库连接池满了超时?先看看你的事务有没有关 42 | 数据库连接池满了超时先看看你的事务有没有关摘要连接池满了报「Timeout waiting for connection」最常见的原因是事务没提交/回滚连接一直不释放。本文讲清排查方法和预防规范。一、问题现象Caused by: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.应用重启后恢复正常但运行一段时间后又出现。二、踩坑现场场景 1Transactional 方法里调了第三方接口// ❌ 事务没提交连接一直占用Transactional(rollbackForException.class)publicvoidprocessOrder(LongorderId){OrderorderorderMapper.selectById(orderId);callThirdParty(order);// 第三方接口耗时 30 秒orderMapper.updateById(order);// 30 秒后事务才提交连接占用了 30 秒}场景 2异常被 catch 吞了事务没回滚// ❌ 异常被吞事务一直不提交Transactional(rollbackForException.class)publicvoidprocess(Longid){try{orderMapper.insert(...);thrownewRuntimeException(失败);}catch(Exceptione){log.error(错误,e);// ❌ 没抛异常事务提交但数据可能不一致}}三、排查步骤3.1 第一步看当前连接池状态// ✅ Spring Boot actuator 暴露连接池指标management:endpoints:web:exposure:include:health,metrics,hikari// 访问GET /actuator/metrics/hikariCP.connections// 关注active活跃连接数、waiting等待中的请求数3.2 第二步找长事务-- MySQL查看当前运行超过 60 秒的事务SELECTtrx_id,trx_state,trx_startedFROMinformation_schema.innodb_trxWHEREtrx_startedNOW()-INTERVAL60SECOND;3.3 第三步看代码里有没有没关闭的连接// ❌ 错误没在 finally 里 close()ConnectionconndataSource.getConnection();try{// ...}finally{// ❌ 漏了 conn.close()}四、正确写法4.1 事务里不要调用第三方接口// ✅ 正确先调第三方再开事务publicvoidprocessOrder(LongorderId){// 1. 先调第三方不在事务里thirdParty.call(orderId);// 2. 再开事务做数据库操作transactionTemplate.execute(status-{OrderorderorderMapper.selectById(orderId);orderMapper.updateById(order);returnnull;});}4.2 事务操作完立即提交// ✅ 正确事务范围尽量小Transactional(rollbackForException.class)publicvoidprocess(Longid){orderMapper.insert(...);// ✅ 事务里只做数据库操作不要有额外逻辑}// 方法结束事务立即提交连接释放4.3 用 Spring 的 TransactionTemplate比注解更灵活// ✅ 推荐编程式事务范围精确控制AutowiredprivateTransactionTemplatetransactionTemplate;publicvoidprocess(Longid){transactionTemplate.execute(status-{orderMapper.insert(...);returnnull;});// ✅ 这里可以做非事务操作如发消息不会占用连接}五、最佳实践✅ 连接池管理的 5 条铁律事务范围尽量小不要在事务里调第三方接口长事务是连接池满的头号原因定期排查用Transactional必须指定rollbackFor Exception.class配置连接池监控HikariCP 的metrics开启连接池大小公式最大连接数 CPU核心数 * 2 磁盘数经验值 HikariCP 推荐配置spring:datasource:hikari:maximum-pool-size:20# 最大连接数minimum-idle:10# 最小空闲连接connection-timeout:30000# 获取连接超时30秒idle-timeout:600000# 空闲连接超时10分钟max-lifetime:1800000# 连接最大存活时间30分钟六、小结连接池满的首要原因长事务事务里调第三方、事务范围太大排查看information_schema.innodb_trx找长事务正确做法事务范围尽量小第三方调用放在事务外面监控 HikariCP 的activeConnections指标超过阈值告警配置合理的连接池大小不是越大越好下一篇预告LIMIT 大偏移量慢查询你的分页写法过时了——LIMIT 100000, 10为什么慢延迟关联优化怎么写更多资料一线大厂Java面试题合集