Java应用启用FCF必须使用UCP而非ojdbc,因FCF依赖UCP监听ONS事件实现故障感知与重连,需配套ons.jar、正确配置ONS参数及数据库端启用服务通知,连接串须极简且禁用TNS级failover配置。

Java应用启用FCF必须用UCP,不是ojdbc自带功能
Oracle的Fast Connection Failover(FCF)不是JDBC驱动原生支持的特性,ojdbc本身不处理连接故障感知与自动重连。真正能用FCF的只有Oracle Universal Connection Pool (UCP),它通过监听Oracle RAC或Data Guard的ONS (Oracle Notification Service)事件来触发连接失效清理和重建。
常见误操作是:在DataSource里只配了jdbc:oracle:thin:@...连接串,再加<property name="fastConnectionFailoverEnabled" value="true"/>——这毫无作用,因为标准ojdbc根本不识别这个参数。
- 必须引入
ucp.jar(对应数据库版本,如19c用ucp-21.7.jar),且版本需与ojdbc一致 -
UCP依赖ons.jar,否则启动时报ClassNotFoundException: oracle.ons.ONS - 连接池初始化时要显式调用
setFastConnectionFailoverEnabled(true),不能只靠URL参数 - RAC环境还需配置
ONS客户端:在JVM启动参数中指定-Doracle.ons.oracleHome=/path/to/oracle/client或通过setONSConfiguration()传入nodes=host1:6200,host2:6200
FCF生效的前提是数据库端已开启服务端通知
即使Java端配对了UCP+ONS,如果Oracle数据库没打开服务端事件推送,FCF永远收不到故障信号。关键检查点不在客户端,而在RAC或DG的数据库实例上:
- 确认数据库已启用
ENABLE_BROKEN服务属性:srvctl modify service -d <db> -s <svc> -j SHORT -B SERVICE_NAME -e SELECT -m BASIC -z 180 -w 5(其中-e SELECT启用FCF事件) - 查当前服务是否注册了FCF支持:
SELECT NAME, FAILOVER_METHOD, FAILOVER_TYPE FROM DBA_SERVICES WHERE NAME = 'your_service';,结果中FAILOVER_METHOD应为BASIC或PRECONNECT,FAILOVER_TYPE为SELECT或SESSION - RAC节点上的
listener.ora必须包含ENABLE_GLOBAL_DYNAMIC_SERVICE = ON,否则ONS无法向客户端广播状态变更 - 不要依赖
tnsping或sqlplus连通性测试来验证FCF——它们不订阅ONS,永远感知不到节点宕机
连接串里别写FAILOVER_MODE,那是TNS层的老方案
看到文档里写(FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC))就往JDBC URL里硬塞?这反而会干扰FCF。UCP的FCF机制和TNS的客户端故障转移(Client-side failover)互斥,混用会导致连接行为不可预测。
立即学习“Java免费学习笔记(深入)”;
正确做法是:连接串保持极简,只提供基础地址与服务名,把高可用逻辑全交给UCP管理。
- ✅ 推荐写法:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=rac-scan)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=myapp_svc))) - ❌ 禁止写法:
...CONNECT_DATA=(SERVICE_NAME=myapp_svc)(FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC))... - UCP内部会自动解析SCAN地址、发现所有节点,并根据ONS事件动态剔除失效实例——你不需要、也不应该在URL里重复声明failover逻辑
- 如果应用仍想保留TNS级重试(比如网络抖动),应改用UCP的
setConnectionPoolStats()调整maxConnectionReuseTime和abandonedConnectionTimeout,而非回退到TNS配置
验证FCF是否真在工作,得看连接池日志和ONS收包
光看应用没报错不等于FCF生效。真实故障下,你会看到连接池主动关闭旧连接、创建新连接,而不是等应用发SQL时才抛SQLException。最容易被忽略的是日志开关没开:
- 启动JVM时加
-Doracle.ucp.level=FINEST -Doracle.ons.level=FINEST,否则默认不输出FCF事件细节 - 正常FCF流程日志应含
ONS event received: node down for instance mydb1、removing connections to failed instance、creating new connection to mydb2 - 若日志里只有
connection validation failed但无ONS事件,说明ONS没连上——检查oracle.ons.nodes地址是否可达、端口6200是否被防火墙拦截 - 注意:FCF只处理“实例崩溃”“节点失联”类故障,不响应SQL执行超时或事务回滚——那是应用层该管的事


















