升级Oracle 19c JDBC驱动后报ORA-02396/ORA-03113错误如何解决
问题根因
该现象不属于19c JDBC驱动的BUG,是Oracle 12c及以上版本驱动的默认行为调整导致的差异:
你遇到的报错核心原因是数据库端已根据2分钟Idle-Time规则主动销毁了空闲连接,但应用侧连接池仍将该连接标记为有效,再次借出使用时就会触发Oracle侧的超时错误。11g版本ojdbc6驱动默认内置了客户端侧无效连接隐式重试逻辑,即使拿到已销毁的连接也会自动尝试重建,所以不会报错;而12c及以上版本驱动为了避免事务执行过程中隐式重试引发的数据不一致风险,默认关闭了该隐式重试逻辑,因此会直接抛出异常。
UCP组件说明
UCP(Universal Connection Pool)是Oracle官方提供的连接池实现,属于可选组件,不是使用19c JDBC驱动的必须依赖,你可以继续使用原有第三方连接池(Druid、HikariCP、DBCP2等),只需调整连接池的有效性检测配置即可解决问题。
具体修复方案
方案1:保持原有连接池,调整配置(推荐,无需修改连接池实现)
所有主流连接池都支持以下配置,调整后即可适配数据库侧的空闲时间规则:
- 设置连接池的最大空闲时间小于数据库的2分钟Idle-Time,建议设为90秒,到期后连接池会自动销毁过期空闲连接
- 开启连接借出前的有效性检测,校验不通过的连接会被自动销毁并重建:
- HikariCP:配置
isUseTestOnBorrow=true,19c驱动兼容JDBC4标准的isValid()接口,无需额外配置测试SQL,也可手动指定connectionTestQuery=SELECT 1 FROM DUAL - Druid:配置
testOnBorrow=true、validationQuery=SELECT 1 FROM DUAL,也可开启testWhileIdle=true配合timeBetweenEvictionRunsMillis参数定时检测空闲连接 - DBCP2:配置
testOnBorrow=true、validationQuery=SELECT 1 FROM DUAL、maxIdleTime=90
- HikariCP:配置
- 可选优化:在JDBC连接串追加驱动级参数
oracle.jdbc.ReadTimeout=180000&oracle.net.CONNECT_TIMEOUT=10000,避免网络异常导致的长时间挂起
方案2:切换为Oracle UCP连接池
如果你要使用UCP连接池,操作步骤如下:
- 引入与ojdbc8版本一致的ucp.jar(你使用的19.11版本驱动需对应19.11版本的ucp.jar)
- 替换原有连接池数据源为UCP官方实现,核心配置示例:
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource(); // 基础连接配置 pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource"); pds.setURL("你的Oracle JDBC连接串"); pds.setUser("数据库用户名"); pds.setPassword("数据库密码"); // 适配数据库空闲时间的核心配置 pds.setMaxIdleTime(90); // 空闲连接最大存活90秒,小于数据库2分钟Idle-Time pds.setValidateConnectionOnBorrow(true); // 借出连接前校验有效性 // 连接池容量配置,根据业务需求调整 pds.setInitialPoolSize(5); pds.setMaxPoolSize(20);
- 业务代码无需修改,直接从UCP数据源获取连接使用即可,UCP会自动处理无效连接的销毁和重建。
内容的提问来源于stack exchange,提问作者user1121201
相关产品推荐
相关产品推荐

