UCP连接池必须显式调用setFastConnectionFailoverEnabled(true)启用FCF,仅设oracle.jdbc.fanEnabled=true无效;FCF依赖服务端FAN、ONS连通性及service名精确匹配,缺一不可。

UCP连接池必须显式启用FCF,setFastConnectionFailoverEnabled(true)不能省
Spring Boot启动后,UCP默认不监听FAN事件,哪怕RAC service已启用FAILOVER_TYPE=SELECT、ONS连通性正常、JDBC URL里写了oracle.jdbc.fanEnabled=true,连接池照样对节点宕机无感。常见现象是应用持续向已下线的RAC实例发请求,报ORA-03113或IO Error: Connection reset,重试间隔长达20–30秒。
解决办法只有一个:在PoolDataSource初始化完成后,立刻调用setFastConnectionFailoverEnabled(true)。这个动作不能靠配置项自动触发,也不能放在setConnectionProperties里传——UCP根本不从那里读这个开关。
- 若用
@Bean方式定义PoolDataSource,需在方法末尾手动调用该方法 - 若集成Spring Boot,推荐用
@PostConstruct或实现InitializingBean.afterPropertiesSet()来确保执行时机 - 验证是否生效:启停一个RAC节点,观察日志中是否有
UCP: FCF event received for service类消息
tnsnames.ora里禁用FAILOVER=ON和LOAD_BALANCE=ON,只留基础描述符
FCF(快速连接故障转移)和TNS层的FAILOVER_MODE逻辑互斥。两者共存会导致路由混乱:FCF主动清理坏连接,而TNS又在地址列表里轮询重连,结果连接卡死在已下线节点上不动。
正确做法是彻底删除FAILOVER=ON、LOAD_BALANCE=ON、整块FAILOVER_MODE配置,只保留最简结构:
(DESCRIPTION= (ADDRESS=(PROTOCOL=TCP)(HOST=myrac-scan)(PORT=1521)) (CONNECT_DATA=(SERVICE_NAME=my_service)) )
- JDBC URL必须用SCAN地址或tnsnames别名,例如
jdbc:oracle:thin:@MYRAC,严禁用Easy Connect格式(如jdbc:oracle:thin:@//rac1-vip:1521/my_service) - 确保
TNS_ADMIN环境变量指向含该tnsnames.ora的目录,否则UCP根本不会加载它 - FCF依赖服务端FAN和ONS通路,务必提前用
onsctl ping -h rac1-vip -p 6200验证
连接亲和性靠connectionLabel控制,不是URL或池参数
Oracle UCP的连接亲和性(Connection Affinity)本质是“把带相同标签的请求尽量复用同一物理连接”,用于维持临时表、包变量等会话级状态。它不等于负载均衡,也不靠修改JDBC URL或池配置就能生效。
实际使用时,每次获取连接前要设置label:
Connection conn = pds.getConnection();
conn.setClientInfo("affinity", "user_123");
// 或更常用:用UCP的connectionLabel机制
pds.setConnectionLabelingCallback(new MyAffinityCallback());
-
MyAffinityCallback需实现ConnectionLabelingCallback接口,根据业务上下文(如用户ID、租户ID)返回label键值对 - label值必须是字符串,且建议控制长度(避免内存膨胀),不要塞JSON或长token
- 注意事务边界:跨事务的label复用可能导致状态污染,尤其在使用
@Transactional时要小心
驱动版本必须匹配Oracle 19c,优先选ojdbc8:21.10.0.0
用错驱动版本会导致连接看似成功,但执行特定SQL时突然失败。典型症状是:能连上、能查DUAL,一跑含序列、LOB或高级队列的语句就报ORA-00904或ORA-22922。
Oracle 19c RAC环境下,必须用com.oracle.database.jdbc:ojdbc8:21.10.0.0(Maven中央库最新稳定版),而不是旧版ojdbc6或com.oracle:ojdbc6。
-
ojdbc6不支持12c+的SCAN地址解析和Application Continuity协议字段 - Spring Boot 3.x项目(JDK17+)直接排除
ojdbc6,它只兼容JDK7 - 若内网无法拉远程依赖,可手动导入jar,但
<scope>system</scope>仅限开发验证,上线前必须切回Maven托管
真正难搞的点不在配置本身,而在验证闭环:FCF是否真被触发、label是否按预期复用、驱动是否悄悄降级了协议支持——这些都得靠真实节点故障+日志+网络抓包交叉确认,光看启动不报错没用。


















