FAILOVER_MODE必须作为CONNECT_DATA的直接子项,否则Oracle Net静默忽略;Java应用须用tnsnames别名连接且设置TNS_ADMIN,TYPE与METHOD需配对(如SESSION+BASIC),否则TAF不生效。
FAILOVER_MODE位置写错,Oracle Net直接忽略
oracle net 只认一种结构:failover_mode 必须作为 connect_data 的直接子项,不能放在 description 顶层、不能塞进 address_list、也不能独立成块。放错位置等于没写,驱动静默跳过,连日志都不报错。
- ✅ 正确:
(CONNECT_DATA = (SERVICE_NAME = mypdb) (FAILOVER_MODE = (TYPE = SESSION) (METHOD = BASIC))) - ❌ 错误:
(DESCRIPTION = (FAILOVER_MODE = ...) (ADDRESS_LIST = ...))—— 参数被完全忽略 - ❌ 错误:
(ADDRESS_LIST = (FAILOVER_MODE = ...) (ADDRESS = ...))—— 同样无效
Java应用没走tnsnames别名,TAF根本不会加载
JDBC Thin 驱动(ojdbc8.jar 或 ojdbc11.jar)只在解析 tnsnames.ora 文件时读取 FAILOVER_MODE。如果 JDBC URL 是 Easy Connect 格式(如 jdbc:oracle:thin:@//rac1-vip:1521/orcl),TAF 彻底不启动,故障时照样报 ORA-03113 或 IO Error: Connection reset。
- 必须把连接定义为 tnsnames 别名,例如
RACDB - JDBC URL 写成
jdbc:oracle:thin:@RACDB,不是 IP 或 SCAN 直连 - 启动 Java 进程前,确保设置了
TNS_ADMIN环境变量指向含tnsnames.ora的目录 - Spring Boot 中不能靠
spring.datasource.url直接传别名——需配合oracle.jdbc.fanEnabled=false和显式配置TNS_ADMIN
TYPE/METHOD配对错误,行为与预期严重不符
TYPE 决定“故障后做什么”,METHOD 决定“什么时候做”。两者不匹配会导致会话中断、查询失败、或连接池爆满,而不是“自动续查”。
-
TYPE = SESSION + METHOD = BASIC:最稳组合。实例宕机后重建新会话,事务需重发,SELECT 自动重执行;适合 DML 场景 -
TYPE = SELECT不是“更强”,它只对已打开的游标有效,且要求 JDBC 显式设置ResultSet.HOLD_CURSORS_OVER_COMMIT,普通应用不配就仍抛ORA-03113 -
METHOD = PRECONNECT在 ojdbc8+ 已废弃,设了也不生效,还可能触发ORA-12519(连接数超限)
RETRIES × DELAY 超出业务容忍窗口,看起来像“卡死”
TAF 故障转移耗时 ≈ RETRIES × DELAY 秒。这个值不是越大越好,而是要对齐应用层超时策略。
- 设
RETRIES=180, DELAY=5→ 最长等 15 分钟才放弃,但 HTTP 接口通常 30 秒就返回504 Gateway Timeout - 设
DELAY=1且RETRIES过大 → 连续重试可能被监听器限流,报ORA-12535 - 生产推荐起步值:
RETRIES=30, DELAY=3(约 90 秒内完成探测与切换),既避开瞬时抖动,又不至于挂太久 -
RETRIES=0表示不重试,首次失败立即报错;不设该参数则用默认值 5
failover=on 就能自动续查”的开关功能,它是一套客户端、驱动、服务端三端协同生效的机制。最容易被忽略的是:**Java 应用是否真正在用 tnsnames 别名、FAILOVER_MODE 是否嵌套在 CONNECT_DATA 下、以及 TYPE/METHOD 是否按实际 SQL 类型选对**——漏掉任一环,故障时都只会看到连接断开,而不是透明切换。











