You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中JdbcTemplate引发PostgreSQL数据库连接泄漏问题排查

分析你的PostgreSQL连接泄漏问题

从你描述的现象和给出的配置代码来看,问题大概率出在Tomcat JDBC连接池的配置遗漏上,而非数据库本身的配置错误。我来一步步拆解原因和解决方案:

为什么会出现连接泄漏?

你提到JdbcTemplate应该自动关闭连接,但部分连接的最后使用时间停留在昨日——这说明这些连接被从池中取出后,没有被正确归还回连接池。虽然JdbcTemplate默认会在执行完SQL操作后自动释放连接(将连接放回池,而非物理关闭),但如果连接池没有配置废弃连接的回收机制,这些被遗弃的连接会一直占用资源,导致连接数持续增长。

你的连接池配置缺少哪些关键参数?

看你的configureDataSource方法,只配置了testWhileIdle、validationQuery和timeBetweenEvictionRunsMillis,但缺少了几个核心的连接回收参数:

1. 废弃连接回收参数

Tomcat JDBC池提供了自动回收长时间未归还连接的机制,你需要开启以下参数:

  • removeAbandoned: 开启废弃连接检测
  • removeAbandonedTimeout: 连接被取出后超过该时间(秒)未归还,就会被标记为废弃并回收
  • logAbandoned: 开启后会记录废弃连接的调用栈,方便定位泄漏点

2. 空闲连接数控制参数

合理配置空闲连接的上限,避免池里堆积过多闲置连接:

  • maxIdle: 连接池允许的最大空闲连接数(建议小于默认的maxActive值,默认maxActive是100)
  • minIdle: 连接池保持的最小空闲连接数,确保有足够的备用连接

修改后的配置示例

把这些参数添加到你的configureDataSource方法中:

private DataSource configureDataSource(String url, String user, String password, String driverClassName){
    DataSource ds = DataSourceBuilder.create()
            .url(url)
            .username(user)
            .password(password)
            .driverClassName(driverClassName)
            .build();
    org.apache.tomcat.jdbc.pool.DataSource configuredDataSource = (org.apache.tomcat.jdbc.pool.DataSource) ds;
    
    // 你已有的配置
    configuredDataSource.setTestWhileIdle(connectionTestWhileIdle);
    configuredDataSource.setValidationQuery(connectionValidationQuery);
    configuredDataSource.setTimeBetweenEvictionRunsMillis(toIntExact(connectionTimeBetweenEvictionRunsMillis));
    
    // 添加的关键配置
    configuredDataSource.setRemoveAbandoned(true);
    configuredDataSource.setRemoveAbandonedTimeout(300); // 设置为5分钟,可根据业务调整
    configuredDataSource.setLogAbandoned(true);
    configuredDataSource.setMaxIdle(10); // 最大空闲连接数
    configuredDataSource.setMinIdle(5); // 最小空闲连接数
    
    return configuredDataSource;
}

额外排查点

虽然JdbcTemplate自动管理连接,但还是建议检查代码中是否存在手动获取Connection但未关闭的情况,比如:

// 这种写法如果忘记调用conn.close(),会直接造成连接泄漏
Connection conn = getQaJdbcTemplate().getDataSource().getConnection();
// ...业务操作
// 遗漏 conn.close();

如果所有数据库操作都通过JdbcTemplate的标准方法(query、update等)执行,那只需要调整连接池配置即可解决问题。

内容的提问来源于stack exchange,提问作者Vitalii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:55:07