先说几个关键点,关于ODP.NET和TAF(透明应用故障转移)的配置,其实有不少容易踩坑的地方,稍不注意就可能导致故障转移完全失效。核心在于,ODP.NET默认对故障转移是“无感”的,必须在代码中明确告知。下面逐步拆解各项要点。
Failover=true 必须显式写在连接字符串里
ODP.NET 默认完全不启用故障转移,哪怕你在 tnsnames.ora 里配置了 FAILOVER_MODE、FAILOVER=YES,也完全不起作用。必须在 .NET 连接字符串中显式加上 Failover=true(注意大小写敏感,不是 Failover=TRUE 或 failover=true)。

典型错误:只改了 tnsnames.ora,没动连接字符串,结果主库宕机后应用直接报 ORA-12154 或卡住不动;或者写了 Failover=True(首字母大写但其余小写),驱动无法识别,相当于没开启。
Failover=true是 ODP.NET 的硬性开关,缺少它,TAF 根本不会启动。- Entity Framework 用户需检查
app.config或web.config中的connectionStrings,确保该参数存在且拼写准确。 - 若用
OracleConnectionStringBuilder动态构造连接串,务必调用builder["Failover"] = "true",不能遗漏。
tnsnames.ora 中 LOAD_BALANCE 和 FAILOVER 必须共存
只写 LOAD_BALANCE=YES 并不能实现故障转移——它只影响首次建连时随机选择地址;一旦连上,后续所有请求都固定绑定该实例,主库挂了也不会自动切换。要真正触发连接时的故障转移,必须同时存在 LOAD_BALANCE=YES 和 FAILOVER=YES,缺一不可。
- 错误配置:
(ADDRESS_LIST = (ADDRESS=...) (ADDRESS=...) (LOAD_BALANCE=YES))→ 无故障转移能力。 - 正确配置:
(ADDRESS_LIST = (ADDRESS=...) (ADDRESS=...) (LOAD_BALANCE=YES) (FAILOVER=YES))。 - 若主库监听进程还在但数据库已挂起(比如 PMON 挂了),Oracle Net 可能无法快速判定失败,超时由
SQLNET.OUTBOUND_CONNECT_TIMEOUT控制,默认 60 秒,建议设为10秒以缩短感知延迟。
TAF 类型决定查询是否重跑
连接成功后发生的故障(如主库运行中突然宕机),能否让正在执行的 SELECT 自动续跑,取决于 TAF 配置中的 TYPE 值和 ODP.NET 版本。
旧版 ODP.NET(如 11.2)只支持 TYPE=SESSION,即断开后重建连接,原有查询结果丢失;只有 12.1+ 才支持 TYPE=SELECT 的透明重执行。
FAILOVER_MODE = (TYPE = SELECT)要求服务端也启用 TAF(ALTER SYSTEM REGISTER后确认监听器注册了服务)。- 服务端未启用 TAF 时,即使客户端写了
TYPE=SELECT,实际降级为SESSION行为。 - 用
SELECT * FROM V$ACTIVE_SERVICES查询服务是否带有FAILOVER_TYPE和FAILOVER_METHOD字段,有值才表示 TAF 已生效。
监听器必须用专用 SERVER,禁用 Shared Server
Data Guard 场景下,必须使用专用服务器连接(Dedicated Server)。Shared Server(MTS)与 TAF 不兼容,会导致故障转移后连接卡死或报 ORA-12514。
检查方式:连接后查询 SELECT server FROM v$session WHERE sid = SYS_CONTEXT('USERENV','SID'),返回 DEDICATED 才安全。
- 监听器配置中不能包含
DISPATCHERS参数,否则默认启用 Shared Server。 - 数据库参数
shared_servers应设为0,并确认local_listener指向的是专用监听器(如LISTENER_DG)。 - 应用连接字符串里不要加
Server=Shared或类似干扰项。
实际生效的关键点很窄:tnsnames.ora 里 FAILOVER=YES + LOAD_BALANCE=YES + FAILOVER_MODE 配置,.NET 连接串里 Failover=true,驱动版本 ≥12.1,服务端监听器是专用模式且注册了 TAF 服务——这五项缺一不可。少一个,故障转移就变成半截子工程。
