odp.net启用taf必须同时满足服务端rac服务显式配置failover_type=select且客户端连接字符串严格指定(failover_mode=(type=select)(method=basic)(retries=n)(delay=m)),缺一不可。

ODP.NET 中启用 TAF(Transparent Application Failover)必须满足服务端和客户端双重条件,缺一不可。只改连接字符串或只配服务端都无效——TAF 不是“开了就自动工作”的开关,而是 Oracle Net 层协同生效的会话级机制。
ODP.NET 的 TAF 依赖服务端 RAC service 显式启用 FAILOVER_TYPE=SELECT
TAF 在 ODP.NET 中不是靠驱动自己实现的重连逻辑,而是监听服务端发布的 FAN(Fast Application Notification)事件,并由 Oracle Net Client 层接管重连。这意味着:
- 服务端必须用
srvctl add service创建 RAC-aware 服务,且明确指定FAILOVER_TYPE=SELECT(例如:srvctl add service -s myapp -r "inst1,inst2" -f -y BASIC -q TRUE -m BASIC -z 5 -w 1) -
srvctl config service -s myapp输出中必须包含Failover type: SELECT,否则 ODP.NET 即使连上了,TAF 也不会激活 - 不能用静态注册的 SID,必须用动态注册的
SERVICE_NAME;监听器状态(lsnrctl status)里该 service 要显示Service has 2 instance(s)且状态为READY - 单实例数据库不支持 TAF(即使配了 FAILOVER_MODE),RAC 或 Data Guard 物理备库才可能触发
连接字符串里必须显式声明 FAILOVER_MODE,不能只写 FAILOVER=true
ODP.NET 托管驱动(Oracle.ManagedDataAccess)不认 setFailoverEnabled(true) 这类 API,也不读取 sqlnet.ora。它只解析连接字符串中的 FAILOVER_MODE 子句,且格式必须严格:
- 完整写法是:
(FAILOVER_MODE=(TYPE=select)(METHOD=basic)(RETRIES=3)(DELAY=2)),全部小写、括号嵌套、无空格 -
TYPE=select是硬性要求:只有正在执行的SELECT(含 FETCH 阶段中断)会被重放;DML 中断后会抛OracleException并回滚事务,需应用层捕获重试 -
METHOD=basic是唯一有效值;preconnect在 ODP.NET 21c+ 已废弃,设了也忽略 - 示例连接字符串:
"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=rac1-vip)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=rac2-vip)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=myapp)(FAILOVER_MODE=(TYPE=select)(METHOD=basic)(RETRIES=3)(DELAY=2))));User Id=scott;Password=tiger;"
使用 OracleConnection.Open() 后,TAF 才真正开始监听实例状态
TAF 不在连接建立前起作用,而是在 OracleConnection.Open() 成功返回后,由底层 Oracle Net Client 启动监听。这意味着:
- 连接池场景下,TAF 对每个物理连接独立生效;但连接复用时若原实例宕机,池中 stale connection 仍会报
OracleException,需配合连接池的验证逻辑(如设置Validate Connection=true) - 不能指望 TAF 处理网络闪断(如 TCP RST);它只响应 Oracle 实例级故障(如实例崩溃、RAC 节点驱逐)
- 测试时别用
tnsping或sqlplus简单连通性验证——它们不触发 TAF 监听;必须用 .NET 代码执行一个长耗时SELECT(如SELECT * FROM v$session_longops),再手动 kill 对应实例进程观察是否自动续查 - 日志可开:
OracleConfiguration.TraceFileLocation = @"C:\temp"+OracleConfiguration.EnableOdpTrace = true,查看 trace 文件中是否有taf: failover started类条目
TAF 的关键复杂点在于它横跨服务端注册策略、网络层协议行为和客户端驱动解析逻辑三层。最容易被忽略的是:服务端 srvctl config service 输出没确认 FAILOVER_TYPE=SELECT,就直接改连接字符串——此时所有参数都是静默失效的。










