FAN生效需服务端推送事件、客户端ONS通道畅通、连接池显式启用FCF三者缺一不可;仅设fanEnabled=true无效,必须验证跨节点ONS互通、service已启动且FAILOVER_TYPE非NONE、禁用TNS层干扰参数。

FAN 不是设个 fanEnabled=true 就能自动工作的。它必须同时满足三个硬性条件:服务端推送事件、客户端 ONS 通道畅通、连接池显式启用 FCF。缺一不可。
验证 ONS 是否真正跨节点互通
ONS 是 FAN 的底层通信管道,onsctl ping 成功只是本地连得上,不代表能收 RAC 推送的 DOWN/UP 事件。
常见错误现象:应用日志里没任何 FAN 日志,连接池在节点宕机后仍往死节点发请求,最终抛 ORA-03113 或连接超时。
必须逐节点验证远程通信:
- 在 rac1 上执行:onsctl ping -h rac2 -p 6113(替换为真实节点名和端口)
- 在 rac2 上执行:onsctl ping -h rac1 -p 6113
- 检查 $CRS_HOME/opmn/conf/ons.config 中的 remoteport,必须与 racgons add_config 注册的端口完全一致
- 所有节点的 localport 不能重复(默认 6113),否则事件会被丢弃
确认 service 已启动且 FAILOVER_TYPE 合法
srvctl add service 只注册元数据,不启动服务——这是绝大多数人连不上、FAN 不触发的根本原因。
使用场景:Java 应用通过 JDBC 连接 SERVICE_NAME,但始终收不到故障通知。
必须执行:
- srvctl start service -d <db> -s <service_name>
- srvctl status service -d <db> -s <service_name> 确认状态为 ENABLED
- 查看该 service 的配置:srvctl config service -d <db> -s <service_name>,确保 Failover type 不是 NONE,应为 SELECT 或 SESSIONJDBC 连接池中必须显式启用 FCF,禁用干扰参数
只在连接字符串加fanEnabled=true 或调用 setProperty("oracle.jdbc.fanEnabled", "true") 是无效的。
关键点:
- 使用 UCP(Universal Connection Pool)时,必须调用:setFastConnectionFailoverEnabled(true)
- 使用原生 JDBC Thin 时,需在获取连接后立即设置:connection.setProperty("oracle.jdbc.fanEnabled", "true")
- 连接字符串中禁止含 LOAD_BALANCE=ON 或 FAILOVER=ON,这些参数会绕过 FCF 路径,在 SCAN 场景下导致连接被路由到已宕机实例
- 若用 UCP,务必关闭隐式缓存:setImplicitCachingEnabled(false),否则 FCF 触发后连接不会被及时清理
检查 ONS 是否由 CRS 正确管理并查看日志
手动运行$ORACLE_HOME/bin/onsctl start 会导致 ONS 加载错误实例,无法接收 RAC 内部事件。
正确启动方式:
- crsctl start resource ora.ons(所有节点都要执行)
- 查看日志定位联通失败根源:$CRS_HOME/log/<host>/client/ons.log
典型错误信息:
- Connection refused → 远程节点 ONS 未启动或防火墙拦截
- Failed to connect to remote host → ons.config 配置错误或网络不通
- 日志里完全没有 publish 或 subscribe 记录 → FAN 事件根本没发出或没收到
FAN 最容易被忽略的点,是把它当成一个“开关型”配置。实际上它是依赖集群基础设施、网络策略、服务状态、连接池行为四层联动的机制。任何一个环节断开,整个链路就静默失效——而错误日志往往不报错,只表现为“没反应”。


















