news 2026/4/18 8:25:28

数据库连接池泄漏:为什么连接越用越少?怎么彻底排查与修复?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据库连接池泄漏:为什么连接越用越少?怎么彻底排查与修复?

网罗开发(小红书、快手、视频号同名)

大家好,我是展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
📣 公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!


文章目录

  • 前言
    • 摘要
    • 描述:为什么连接池说我的连接泄漏了?
      • 什么叫连接泄漏?
    • 题解答案:如何彻底解决连接池泄漏?
      • 1. 使用 try-with-resources 自动关闭连接(最关键)
      • 2. 检查连接池最大连接数,避免业务量增长导致耗尽
      • 3. 开启 leakDetectionThreshold,让连接池自动“报警”
    • 代码解析:一个典型的泄漏案例(错误示例)
    • 正确示例 Demo:用 try-with-resources 自动关闭资源
    • 启用 leakDetectionThreshold:让 HikariCP 自动抓到泄漏点
    • 最大连接数问题:为什么连接泄漏看起来像“数据库压力太大”?
    • 实际场景分析:哪些地方最容易发生泄漏?
      • 场景 1:在循环中不断创建连接
      • 场景 2:异常抛出时 finally 被遗漏
      • 场景 3:使用多层封装(容易忘记关闭)
      • 场景 4:并发任务中手动开启连接,但不关闭
    • 示例测试与结果
    • 总结

前言

在后端项目里,数据库连接池泄漏几乎是所有人都踩过的坑。
一旦发生泄漏,症状非常典型:

  • 系统运行一段时间后请求突然变慢
  • 数据库连接数飙升到 max active
  • 错误日志出现 “Too many connections”
  • 必须重启服务才能恢复

最让人头疼的是:问题通常不是数据库本身,而是代码里有连接没被关闭—— 结果池子永远等不到归还,连接越用越少。

这篇文章我会讲清楚:

  1. 为什么连接池会泄漏
  2. 真实项目里的常见场景
  3. 如何让 HikariCP / DBCP 自动帮你找出泄漏点
  4. 可运行 Demo + 实战级代码解析

如果你也遇到过“线上数据库突然卡死,重启就好了”的情况,这篇文章非常值得收藏。

摘要

数据库连接池泄漏本质上是:连接被借出(getConnection)后没有被正确关闭(close)。
文章将从代码层面、连接池配置、监控机制三个角度来定位和解决问题。提供可运行 Demo(含 try-with-resources 正确写法!),以及 leakDetectionThreshold 和最大连接数配置的最佳实践。

描述:为什么连接池说我的连接泄漏了?

什么叫连接泄漏?

非常简单:
借出去的连接,没有再还回去。

连接池不是无限的,默认提供 10~50 个连接。如果你有一段代码没有关闭连接,那么每执行一次,连接池就少一个可用连接。

当连接数被占满后,后续请求就会卡死或直接报异常。

题解答案:如何彻底解决连接池泄漏?

解决方案大致分三步:

1. 使用 try-with-resources 自动关闭连接(最关键)

Java 中连接、Statement、ResultSet 都是 AutoCloseable,可以用 try-with-resources 自动 close。

2. 检查连接池最大连接数,避免业务量增长导致耗尽

例如 HikariCP 的maximumPoolSize,太小容易阻塞,太大又浪费资源。

3. 开启 leakDetectionThreshold,让连接池自动“报警”

这是 HikariCP 的神器配置:
只要某个连接超过一定时间没关闭,它就会打印堆栈信息,告诉你是哪一行代码泄漏的。

代码解析:一个典型的泄漏案例(错误示例)

下面的代码很多人都会这么写,但这是导致泄漏的元凶之一:

publicUsergetUser(intuserId)throwsSQLException{Connectionconn=dataSource.getConnection();// 借出连接PreparedStatementstmt=conn.prepareStatement("SELECT * FROM user WHERE id=?");stmt.setInt(1,userId);ResultSetrs=stmt.executeQuery();if(rs.next()){returnnewUser(rs.getInt("id"),rs.getString("name"));}// 问题:这里没有关闭任何资源!returnnull;}

问题:

  • conn 没有关闭
  • stmt 没有关闭
  • rs 没有关闭
  • 意味着连接池永远等不到这个连接回收

你的系统最多只需要几十次调用就会把连接全占满。

正确示例 Demo:用 try-with-resources 自动关闭资源

这是连接池官方推荐的最佳写法,绝对不会泄漏:

publicUsergetUser(intuserId){Stringsql="SELECT * FROM user WHERE id=?";try(Connectionconn=dataSource.getConnection();// 自动关闭PreparedStatementstmt=conn.prepareStatement(sql);){stmt.setInt(1,userId);try(ResultSetrs=stmt.executeQuery()){// 自动关闭if(rs.next()){returnnewUser(rs.getInt("id"),rs.getString("name"));}}}catch(SQLExceptione){thrownewRuntimeException("Query error",e);}returnnull;}

为什么安全?

  1. try(…) 自动调用 close()
  2. 不需要手写 finally
  3. 每一层资源都被正确回收
  4. 不管异常是否发生,连接都不会泄漏

这是避免泄漏的最终方案。

启用 leakDetectionThreshold:让 HikariCP 自动抓到泄漏点

在开发环境或测试环境中,你可以开启这个配置:

spring:datasource:hikari:leak-detection-threshold:2000# 超过2秒未关闭就打印堆栈

或 Java 配置:

HikariConfigconfig=newHikariConfig();config.setLeakDetectionThreshold(2000);// 2秒

运行后,如果某个连接超过 2 秒没关闭,会看到类似日志:

Connection leak detected: connection com.mysql.jdbc.JDBC4Connection@xxxx was not closed. Stack trace: at com.xxx.Repository.getUser(Repository.java:42) at com.xxx.Service.call(Service.java:25)

看到这一段你就知道泄漏在哪里了,比你人工排查有效一百倍。

最大连接数问题:为什么连接泄漏看起来像“数据库压力太大”?

很多时候我们误以为数据库崩了,其实是连接池被耗尽了。

比如:

maximumPoolSize:10

在这个配置下:

  • 10 个连接都泄漏
  • 第 11 个请求开始 → 直接阻塞或报错

这也是为什么:

  • 重启服务 → 自动释放连接 → 一切恢复正常
  • 跑一段时间 → 又挂了

如果你有大量并发接口访问数据库,一定要适当调高连接池大小:

maximumPoolSize:30minimumIdle:5

但不要盲目调太高,否则数据库本身会被拖垮。

实际场景分析:哪些地方最容易发生泄漏?

场景 1:在循环中不断创建连接

for(...){Connectionconn=dataSource.getConnection();// 未关闭...}

很快连接池耗尽。

场景 2:异常抛出时 finally 被遗漏

try{Connectionconn=ds.getConnection();...if(error)thrownewRuntimeException();}catch(Exceptione){log.error(e);}// 没有 finally,资源永远泄漏

场景 3:使用多层封装(容易忘记关闭)

例如 Service → Repository → Helper → DAO
每一层都可能忘记关闭 ResultSet 或 Statement。

场景 4:并发任务中手动开启连接,但不关闭

线程池 + 手写 JDBC 特别容易踩坑。

示例测试与结果

使用错误代码 + 启用 leakDetectionThreshold,会得到:

Connection leak detected ... at com.xxx.Repository.getUser(Repository.java:42)

使用 try-with-resources 改写,并开启 Hikari 日志:

  • 连接借出、归还都正常
  • 系统运行稳定
  • 不会再出现连接耗尽、阻塞、重启恢复等问题

这是最可靠的验证方式。

总结

数据库连接池泄漏本质上是连接借出后没有关闭,导致连接池永远无法回收资源。
要彻底解决这个问题,你需要做到:

  1. 优先使用 try-with-resources,自动关闭所有 JDBC 资源
  2. 合理配置最大连接数,避免高峰期被耗尽
  3. 开启 leakDetectionThreshold,让连接池帮你自动排查泄漏堆栈

只要这三步做到位,你的数据库连接池就能保持长期稳定,不会再出现“运行 10 分钟就卡死”这种恼人的情况。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 12:34:18

力扣知识点总结

一、字符串处理类 代表题目: - 罗马数字转整数 - 最长回文子串 - Z字形变换 - 无重复字符的最长子串 核心知识点: 1. 哈希表映射(罗马数字转整数):用哈希表存储罗马字符与数值的对应关系,遍历字符串时通过“…

作者头像 李华
网站建设 2026/4/12 16:24:10

企业安全管理系统功能解析与代码实现

在现代企业的安全管理中,如何高效地整合和管理大量的安全数据、法规、人员和设备信息,已成为许多企业面临的挑战。本文将介绍一个企业安全管理系统的设计思路,包括法律法规查询、安全管理、人员管理等功能,并提供相应的代码示例&a…

作者头像 李华
网站建设 2026/4/18 7:01:39

解密 PKI:数字证书背后的网络安全基石

无论是电商交易、远程办公还是数据传输,都需要解决身份认证、数据加密等核心问题。而公钥基础设施(PKI)作为信息安全技术的核心,正是支撑这些安全需求的底层架构。它通过数字证书与公钥技术的结合,构建起一套可信的网络…

作者头像 李华
网站建设 2026/4/18 7:00:01

Wan2.2-T2V-A14B在社交媒体爆款视频生成中的实战效果

Wan2.2-T2V-A14B在社交媒体爆款视频生成中的实战效果 你有没有刷到过那种“一秒入梦”的短视频?——樱花纷飞中旋转起舞的女孩,清晨阳光下缓缓旋出的口红,或是极光下奔跑的雪橇犬……画面精致得不像AI,动作流畅得仿佛真人拍摄。 …

作者头像 李华
网站建设 2026/4/18 7:03:15

终极网络性能测试指南:iperf3跨平台工具完整使用教程

终极网络性能测试指南:iperf3跨平台工具完整使用教程 【免费下载链接】iperf3网络测试工具-Win64AndroidAPK iperf3 网络测试工具 - Win64 Android APK 项目地址: https://gitcode.com/open-source-toolkit/01598 iperf3是一款专业的网络性能测试工具&#…

作者头像 李华
网站建设 2026/4/18 7:23:14

AI改造最难啃的行业,万亿基建求解“效率”与“可信”

来源:21世纪经济报道 记者:孔海丽全球基础设施行业走到了变革的十字路口。一边是预计到2025年将达到10万亿美元的全球建设支出热潮,另一边是,行业生产率数十年来几乎没有改善。人工智能(AI)在各个行业都普…

作者头像 李华