Jooq耗尽Hikari连接池全部数据库连接问题求助
Jooq+Hikari连接池耗尽问题排查与解决
问题现象
使用Jooq结合Hikari连接池操作MySQL,配置最大连接数100,但仅执行少量fetchOne查询后就触发连接耗尽错误:
HikariPool-1 - Connection is not available, request timed out after 10007ms.
Hikari统计数据显示所有连接均处于活跃状态,无空闲连接:
HikariPool-1 - Before cleanup stats (total=100, active=100, idle=0, waiting=0) HikariPool-1 - After cleanup stats (total=100, active=100, idle=0, waiting=0)
排查方向与解决方法
1. 检查Jooq的Settings配置
默认情况下,基于DataSource创建的DSLContext会自动管理连接的获取与释放,但如果手动开启了keepConnectionOpen=true,会导致连接无法自动归还到连接池。确认你的配置:
// 确保该配置为false(默认值即为false,若被修改会引发泄漏) settings.setKeepConnectionOpen(false);
2. 开启Hikari连接泄漏检测
通过Hikari的泄漏检测功能定位未归还连接的代码位置,在Hikari配置中添加:
// 设置泄漏检测阈值(单位:毫秒),例如2秒 config.setLeakDetectionThreshold(2000);
当连接被占用超过阈值时,Hikari会在日志中打印连接的调用堆栈,直接定位泄漏代码段。
3. 排查手动管理连接的代码
如果代码中存在手动从DataSource获取连接的逻辑,必须确保连接被正确关闭,推荐使用try-with-resources自动管理:
// 正确示例:用try-with-resources自动关闭连接 try (Connection conn = dataSource.getConnection()) { // 执行数据库操作 }
避免直接获取连接后不关闭的写法,这会直接导致连接泄漏。
4. 检查事务处理逻辑
如果使用手动事务管理(而非Jooq的事务lambda),必须确保事务最终被提交或回滚:
// 错误示例:开启事务后未提交/回滚 Transaction tx = dslContext.beginTransaction(); try { // 执行操作 // 遗漏commit } catch (Exception e) { // 遗漏rollback }
推荐使用Jooq的事务lambda,它会自动处理提交与回滚,避免连接泄漏:
dslContext.transaction(tx -> { tx.dsl().fetchOne(TWITTER_USER, TWITTER_USER.ID.eq(currentUserId)); // 操作完成自动提交,异常自动回滚 });
5. 确认fetchOne的使用方式
正常情况下,dslContext.fetchOne(...)会自动完成连接的获取与释放,无需额外处理。但如果查询后持有了未关闭的ResultSet或Statement引用,可能间接导致连接无法释放,确保查询后不保留这些资源的引用。
内容的提问来源于stack exchange,提问作者Mahdi
相关产品推荐
相关产品推荐

