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

Spring JdbcClient致Oracle会话过多及HikariCP连接超时问题求助

问题分析与解决方案

一、DriverManagerDataSource 会话激增问题

DriverManagerDataSource本身不支持连接池,每次调用JdbcClient时都会创建新的物理数据库连接——它只是简单封装了DriverManager,每次请求新建连接、用完直接关闭物理连接而非放回池,高并发下必然导致会话数飙升至4k,引发资源耗尽。

解决办法:直接弃用DriverManagerDataSource,使用HikariCP(Spring Boot默认连接池)或其他成熟连接池,这是唯一可行的方案。

二、HikariCP 连接超时问题(Connection is not available)

你怀疑连接未被正确释放是合理的,结合代码片段来看,问题大概率出在Stream资源未关闭上。

问题根源

jdbcClient.query(...).stream()返回的Stream绑定了数据库连接,仅调用findFirst()时,若Stream提前终止或发生异常,连接可能无法自动释放。HikariCP的连接被持续占用无法回池,后续请求拿不到连接最终超时。

解决方案

1. 用try-with-resources确保Stream关闭

通过try-with-resources语法自动关闭Stream,强制释放连接回池:

@Autowired
private JdbcClient jdbcClient;

public String getQueryResult(String id) {
    try (Stream<String> stream = jdbcClient.sql("query")
            .param("id", id)
            .query(String.class)
            .stream()) {
        return stream.findFirst().orElse("");
    }
}

try-with-resources会自动关闭实现AutoCloseable接口的资源,这里关闭Stream时会同步释放绑定的数据库连接。

2. 检查HikariCP配置合理性

若上述修改后问题仍存在,排查以下配置:

  • spring.datasource.hikari.maximum-pool-size:若设置过小,无法应对并发请求,建议按服务器CPU核数调整(例如核数*2+1)
  • spring.datasource.hikari.leak-detection-threshold:开启连接泄漏检测,设置为2000毫秒,日志会打印泄漏连接的调用栈,帮助定位问题:
    spring.datasource.hikari.leak-detection-threshold=2000
    

3. 确认JdbcClient绑定正确数据源

确保JdbcClient基于HikariDataSource创建,而非误用DriverManagerDataSource。Spring Boot默认会自动创建HikariDataSource,若自定义数据源配置,需明确返回HikariDataSource:

@Configuration
public class DataSourceConfig {
    @Bean
    public DataSource dataSource(Environment env) {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(env.getProperty("spring.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.password"));
        dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
        // 其他Hikari配置
        return dataSource;
    }

    @Bean
    public JdbcClient jdbcClient(DataSource dataSource) {
        return JdbcClient.create(dataSource);
    }
}

4. 排查Oracle会话状态

用Oracle语句查看会话状态,确认连接是否被占用未释放:

SELECT s.sid, s.serial#, s.status, s.username, s.program
FROM v$session s
WHERE s.username = 'YOUR_DB_USER';

若存在大量ACTIVE状态且归属你的应用的会话,说明确实存在连接泄漏,结合泄漏检测日志定位代码。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:35:16