UCP必须显式调用setFastConnectionFailoverEnabled(true),仅设oracle.jdbc.fanEnabled=true无效;FCF依赖服务端FAN、ONS连通性及service名精确匹配,缺一不可。
UCP 必须显式启用 FCF,setFastConnectionFailoverEnabled(true) 不能省
只在 jdbc url 或连接属性里设 oracle.jdbc.fanenabled=true 不起作用。ucp 的快速连接故障转移(fcf)是主动监听 fan 事件的机制,必须通过池对象显式开启。否则即使服务端 fan 正常、ons 通路完好,连接池也不会响应 down 事件。
常见错误现象:应用在 RAC 节点宕机后仍持续向坏实例发请求,报 ORA-03113 或 IO Error: Connection reset,重试间隔长达 20–30 秒。
-
PoolDataSource初始化后必须调用setFastConnectionFailoverEnabled(true) - 不能依赖连接属性传递,UCP 不会从
setConnectionProperties自动识别该开关 - 若使用 Spring Boot + UCP,需通过
@PostConstruct或InitializingBean阶段手动触发该方法
tnsnames.ora 里禁用所有 TNS 层重试参数,FCF 和 FAILOVER_MODE 互斥
FCF 是事件驱动的主动失效感知,而 FAILOVER=ON 或完整的 FAILOVER_MODE 块属于 TNS 层被动重试逻辑。两者同时存在会导致连接路由混乱:一个走事件清理,一个在地址列表里轮询重连,结果可能是连接卡在已下线节点上不动。
使用场景:你已确认 RAC service 启用了 FAN(srvctl config service 显示 FAILOVER_TYPE=SELECT),且 ONS 连通性验证通过(onsctl ping -h rac1-vip -p 6200 成功)。
- tnsnames.ora 中只保留基础连接信息,例如:
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myrac-scan)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=my_service))) - 彻底删除
FAILOVER=ON、LOAD_BALANCE=ON、FAILOVER_MODE块 - JDBC URL 必须用 SCAN 地址或 tnsnames 别名,不能用 Easy Connect 格式(如
jdbc:oracle:thin:@//rac1-vip:1521/my_service)
连接亲和性靠 connectionLabel 实现,不是靠 URL 或连接池配置
Oracle UCP 的连接亲和性(Connection Affinity)本质是“把带相同标签的请求尽量路由到同一物理连接”,用于保持会话级状态(如临时表、包变量)。它不等于负载均衡或实例绑定,也不是靠修改 JDBC URL 或池参数就能生效。
立即学习“Java免费学习笔记(深入)”;
容易踩的坑:以为设置 setConnectionPoolName("affinity_pool") 或在 URL 加 ?connectTimeout=30 就能实现亲和——这些对亲和性完全无效。
- 必须在获取连接时传入
java.util.Properties,其中 key=connectionLabel,value 是字符串标签(如"user_id=12345") - 后续同标签的请求,UCP 才会优先复用已有连接;标签不同则新建
- 标签值需业务可控、低基数(避免每请求都生成唯一 UUID,否则亲和失效)
- 若用 HikariCP 等通用池,无法支持此特性——这是 UCP + Oracle 数据库协同的私有协议
service 名大小写敏感且必须与 srvctl 定义完全一致
FCF 事件是按 service 名广播的,UCP 内部用该名称注册监听器。哪怕只差一个字母或空格,客户端就收不到任何 FAN DOWN/UP 事件,整个 FCF 彻底静默。
性能影响:服务名不匹配时,连接池既不会自动剔除坏连接,也不会重建新连接,所有请求最终堆积在失效连接上,表现为线程阻塞、超时雪崩。
- 执行
srvctl config service -d mydb,确认输出中的Service name:字段(如my_service) - tnsnames.ora 和 JDBC URL 中的 service 名必须逐字符一致,包括下划线、中划线、大小写
- 检查 RAC service 是否启用通知:
srvctl config service -d mydb -s my_service | grep "Notification"应返回enabled - 若 service 是通过
srvctl add service添加的,确保加了-e SELECT或-e SESSION参数


















