Java应用Oracle高可用故障转移生效的关键是UCP与FAN事件链路对齐:必须调用setFastConnectionFailoverEnabled(true),禁用TNS层FAILOVER参数,确保service名大小写一致、ONS连通、监听注册,并将connection-timeout设为30秒以上。

Java应用要让Oracle高可用故障转移真正生效,不是靠“加个重试”或“换URL”,而是必须让UCP连接池与Oracle Data Guard / RAC的FAN事件链路对齐——漏掉setFastConnectionFailoverEnabled(true)、混用FAILOVER_MODE、或service名大小写不一致,都会导致切换卡在20秒以上,甚至完全失效。
为什么启用FCF后Java仍报Connection reset?
这不是数据库没切成功,而是UCP根本没收到FAN事件,或收到了却没响应。常见断点有三个:
-
setFastConnectionFailoverEnabled(true)没调用——仅设oracle.jdbc.fanEnabled=true无效,UCP不从连接属性自动识别该开关 - 服务端FAN未启用:检查
srvctl config service -d <db></db>输出中FAILOVER_TYPE是否为SELECT或SESSION,而非NONE - ONS通信失败:用
onsctl ping -h rac1-vip -p 6200逐节点验证,不能只信本地onsctl ping
tnsnames.ora里能不能配FAILOVER=ON?
不能。FCF是事件驱动的主动感知机制,而FAILOVER=ON或完整的FAILOVER_MODE块属于TNS层被动轮询逻辑,两者同时存在会导致连接路由混乱。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- tnsnames.ora中只保留基础连接信息,例如:
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myrac-scan)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=my_service))) - 彻底删除
FAILOVER=ON、LOAD_BALANCE=ON、FAILOVER_MODE等所有TNS层重试参数 - JDBC URL必须用SCAN地址或tnsnames别名,禁用Easy Connect格式(如
jdbc:oracle:thin:@//rac1-vip:1521/my_service)
如何验证UCP是否真正在响应FAN事件?
光看日志不够,得从连接行为反推:
立即学习“Java免费学习笔记(深入)”;
- 模拟RAC节点宕机后,观察
pool.getAvailableConnectionsCount()是否在1–3秒内归零再重建——若延迟超5秒,说明FCF未触发 - 确认
connectionPool.setImplicitCachingEnabled(false)已关闭,否则失效连接可能被缓存复用 - service名必须与
srvctl add service创建时完全一致(大小写敏感),且该service已注册到监听器(lsnrctl status可见) - 连接字符串中禁用
testOnBorrow类健康检查,它会干扰TAF/FCF的连接重建流程
最常被忽略的一点:FSFO切换后新主库监听就绪有几秒延迟,此时连接池若用默认connection-timeout=10s,大概率超时失败而非自动重试——务必设为30s以上,并配合setConnectionValidationTimeout(5)避免验证阻塞。

















