Oracle 19c必须用ojdbc8,因其是唯一兼容JDK 8–17+且全面支持19c新特性(如Application Continuity、Sharding元数据)的驱动;ojdbc6因方法缺失报NoClassDefFoundError,ojdbc10则因TLS 1.3或Wallet配置不兼容易致连接失败。
Oracle 19c JDBC驱动必须用ojdbc8,别碰ojdbc6或ojdbc10
spring boot 3 基于 java 17+,而 oracle 官方明确要求:ojdbc8(com.oracle.database.jdbc:ojdbc8)是唯一兼容 java 17 且全面支持 oracle 19c 的驱动。用 ojdbc6 会直接抛 java.lang.noclassdeffounderror: java/sql/driver;用 ojdbc10 则可能因 tls 1.3 或 wallet 配置不兼容导致连接失败。
正确做法是删掉旧驱动,显式声明:
<dependency><groupid>com.oracle.database.jdbc</groupid><artifactid>ojdbc8</artifactid><version>21.10.0.0</version></dependency>
注意:ojdbc8 的 21.10.0.0 版本已通过 Oracle 19c 企业版 + RAC 场景验证,比早期 19.19.0.0 更稳定。
spring.datasource.url 必须带 oracle.net.CONNECT_TIMEOUT 和 oracle.net.READ_TIMEOUT
Oracle 默认的网络超时极长(常达数分钟),一旦数据库端挂起或防火墙中断,HikariCP 会卡在 getConnection() 上,拖垮整个线程池。你不能只靠 connection-timeout 拦截——它只管池内排队,不管底层 TCP 握手或 SQL 执行。
必须在 JDBC URL 里硬编码网络层超时:
spring:
datasource:
url: jdbc:oracle:thin:@//db-host:1521/ORCLPDB1?oracle.net.CONNECT_TIMEOUT=5000&oracle.net.READ_TIMEOUT=30000&useUnicode=true&characterEncoding=UTF-8
-
oracle.net.CONNECT_TIMEOUT=5000:TCP 连接建立超时,设为 5 秒,避免 DNS 解析慢或端口不通时无限等待 -
oracle.net.READ_TIMEOUT=30000:Socket 读取超时,设为 30 秒,覆盖长查询、LOB 传输等场景 - 不要加
oracle.jdbc.ReadTimeout—— 它已被废弃,且与oracle.net.READ_TIMEOUT冲突
maximum-pool-size 要小于 Oracle 的 processes 参数,且留足余量
Oracle 19c 实例默认 processes=300,但这个值包含后台进程(PMON、SMON)、专用服务器连接、以及你的应用连接。如果 HikariCP maximum-pool-size 设到 200,再叠加几个监控工具连上来,很容易触发 ORA-00020: maximum number of processes (300) exceeded。
安全计算方式:
- 查当前 Oracle 实例的
processes值:SELECT name, value FROM v$parameter WHERE name = 'processes'; - 预留至少 30% 给系统和 DBA 工具:比如
processes=300→ 最大允许应用连接 ≈ 210 - 单个 Spring Boot 实例建议 ≤ 50;若部署 4 个实例,总连接数 ≤ 200,才真正安全
- 高并发写场景(如批量导入)可临时调高,但必须配合
idle-timeout缩短空闲时间,加速连接释放
max-lifetime 必须比 Oracle 的 sqlnet.ora 中 expire_time 小至少 30 秒
Oracle 19c 默认启用 Dead Connection Detection(DCD),由 sqlnet.ora 中的 SQLNET.EXPIRE_TIME=10(单位:分钟)控制。这意味着空闲 10 分钟的连接会被 Oracle 主动断开,但 HikariCP 不知道,仍把它当有效连接放回池中,下次取出就报 java.sql.SQLRecoverableException: Closed Connection。
解决方案不是关 DCD(不安全),而是让 HikariCP 主动“先下手”:
- 确认数据库端
SQLNET.EXPIRE_TIME值(联系 DBA 或查 $ORACLE_HOME/network/admin/sqlnet.ora) - HikariCP 的
max-lifetime必须设为(expire_time × 60) − 30秒,例如 DCD 是 10 分钟 →max-lifetime: 597000(9 分 57 秒) - 同时配
keepalive-time: 300000(5 分钟),让 HikariCP 每 5 分钟对空闲连接发一次isValid()探活,进一步降低断连概率
这个差值必须严格保持,否则就会出现“连接被 Oracle 杀了,HikariCP 还在用”的经典雪崩起点。











