Oracle RAC应用故障快速切换核心依赖FAN事件驱动机制,而非客户端轮询或超时重试;FAN由服务端主动推送DOWN/UP事件,客户端通过FCF实现事件触发式连接池自愈,需正确配置ONS互通、启用_fan_events、显式设置fanEnabled及匹配service的FAILOVER_TYPE。
oracle rac 实现应用故障快速切换,核心不靠客户端轮询或超时重试,而是依赖 fan(fast application notification)事件驱动机制——服务端主动推送 down/up 事件,客户端收到后立即清理失效连接、重建新会话。fcf(fast connection failover)是这一机制在 jdbc/ucp 等客户端的落地实现,不是“自动重连”,而是“事件触发式连接池自愈”。
为什么 onsctl ping 通了还不行?ONS 进程运行 ≠ FAN 事件可达
ONS(Oracle Notification Service)是 FAN 的底层通道,但它的配置和运行状态常被误判:
-
onsctl ping只验证本地 ONS 进程响应,不检测跨节点通信;必须用onsctl ping -h验证集群内所有节点间 ONS 互通-p - 配置文件
$CRS_HOME/opmn/conf/ons.config中的remoteport必须与racgons add_config注册的端口一致,且所有节点的localport不能冲突(默认 6113) - ONS 必须由 CRS 管理启动(
crsctl start resource ora.ons),不能手动用$ORACLE_HOME/bin/onsctl start启动——后者用的是错误的ORACLE_HOME下的 ONS,无法接收 RAC 内部事件 - 检查日志:
$CRS_HOME/log/中出现/client/ons.log Connection refused或Failed to connect to remote host表示 ONS 联通失败
JDBC 连接字符串里加 FAILOVER=ON 没用?FCF 不走 TNS 层重试逻辑
Connect-time failover(如 tnsnames.ora 中 FAILOVER=ON)和 FCF 是两套机制:前者只在初始建连阶段生效,后者作用于已建立连接的运行时场景。FCF 完全不依赖 TNS 地址列表顺序或重试次数。
- 启用 FCF 必须显式设置连接属性:
connection.setProperty("oracle.jdbc.fanEnabled", "true")(JDBC)或 UCP 中配置setFastConnectionFailoverEnabled(true) - 连接字符串中不能含
LOAD_BALANCE=ON或FAILOVER=ON—— 这些会干扰 FCF 的事件响应路径,尤其在 SCAN 场景下容易导致连接被错误路由到已宕机实例 - 服务名(
SERVICE_NAME)必须对应 RAC 中启用了ENABLED状态的 service(查srvctl config service -d),且该 service 的FAILOVER_TYPE应设为SELECT或SESSION,不能是NONE - 若使用 UCP,必须禁用隐式缓存(
setImplicitCachingEnabled(false)),否则 FCF 事件无法触发连接清理
FAN 事件收不到?检查 client 端订阅配置和数据库 service 层开关
FAN 事件从数据库发出需满足两个前提:服务端发布开关打开 + 客户端成功订阅远程 ONS。常见断点在订阅环节。
- JDBC 客户端需通过
OracleDataSource.setONSConfiguration("nodes=rac1:6200,rac2:6200")显式声明 ONS 节点列表,不能只依赖本地ons.config - RAC 所有节点的
init.ora中必须启用_enable_fan_events=TRUE(11gR2+ 默认开启,但某些补丁集可能关闭) - 确认 service 已启用 FAN:
srvctl config service -d输出中应含-s FAN registration: YES - 若使用 Data Guard,主备库都需配置 ONS 并注册对方地址(
racgons add_config同时加入主、备 VIP),否则角色切换后 FAN 事件无法送达原客户端
FCF 回滚事务失败?注意 FAN DOWN 事件不保证事务原子性
FAN 的 DOWN 事件只通知“连接不可用”,不携带事务上下文。客户端收到事件后执行的清理动作是否包含回滚,完全取决于你使用的连接池或框架逻辑。
- JDBC-UCP 默认会在标记连接无效前尝试
rollback(),但前提是连接尚未物理中断(即 socket 还处于 ESTABLISHED 状态);若网络已断开,rollback()会抛SQLException,此时需业务层捕获并处理 - 不要依赖 FCF 自动恢复长事务(如未提交的 DML 块);FAN 事件触发的是连接级清理,不是事务级补偿
- 在 Web 应用中,若使用 Spring + UCP,需确保
TransactionSynchronizationManager在收到 FAN 事件后能及时释放绑定的事务资源,否则可能引发 connection leak - 最易忽略的一点:FCF 不支持 OCI-based driver(如旧版 thin driver 以外的连接方式),仅适用于 JDBC-TYPE4 和 UCP;OCI 连接只能靠 TAF(Transparent Application Failover),而 TAF 不支持 DML 重放











