TAF启用需同时配置FAILOVER_MODE参数且驱动匹配,服务端注册、TNS解析、异常捕获及连接池适配缺一不可。

确认TAF是否已在连接串中正确启用
光写FAILOVER=true没用,必须和完整的FAILOVER_MODE参数共存,且驱动版本要匹配。ojdbc8+ 驱动下,FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC)(RETRIES=3)(DELAY=5)这整段必须原样出现在连接串里,不能拆开、不能缩写。
常见错误包括:
- 只加了
failover=true但漏掉FAILOVER_MODE,驱动直接忽略TAF逻辑 - 把
TYPE=SESSION误写成TYPE=SESSIONS或大小写混用(Oracle Net严格区分大小写) - 连接串里用了
SID而非SERVICE_NAME,服务端无法按service粒度触发故障转移 - 没配
loadBalance=true(RAC场景)或没确保ADDRESS_LIST含至少两个有效地址(DG场景)
验证TNS和服务端注册是否生效
TAF不是纯客户端行为,服务端TNS配置和服务注册状态决定它能不能被触发。应用连不上≠TAF失效,很可能是服务根本没注册到监听器。
检查步骤:
- 在数据库侧执行
lsnrctl status,确认SERVICE_NAME(如orcl_svc)已显示为STATUS=READY,且有FAILOVER=YES标记 - 查服务是否由
srvctl add service创建(非静态注册),并带-r指定首选实例(主库所在节点) - 用
tnsping DG_SERVICE测试TNS别名能否解析并返回多个地址;再用sqlplus /@DG_SERVICE手动连,主库宕机后观察是否自动切到备库地址 - 如果
tnsping通但sqlplus连不上,大概率是FAILOVER_MODE没写进tnsnames.ora对应条目里
模拟故障时观察应用层真实行为
TAF不是静默重连,它会在连接断开瞬间抛出明确异常。不捕获这些异常,线程就挂了,TAF流程根本走不完。
典型可捕获的异常信号:
-
java.sql.SQLRecoverableException,SQLState为08006或错误信息含IO Error: Connection reset - Oracle原生错误码:
ORA-03113、ORA-03114、ORA-1012、ORA-25402(后者表示事务需回滚,说明TYPE=SELECT生效但DML不重放)
实操建议:
- 写一个最小化测试类,用
while(true)循环执行简单SELECT SYSDATE FROM DUAL,并在catch块里打印堆栈+休眠1秒后继续 - 在执行中手动杀主库监听:
lsnrctl stop,观察是否在DELAY间隔后自动连上备库地址 - 注意:不要用
kill -9杀PMON进程来模拟宕机——那会触发实例崩溃恢复流程,TAF不处理这种级别故障
避开连接池对TAF的干扰
UCP或HikariCP这类连接池默认的健康检查机制,会主动探测连接有效性,反而破坏TAF的重建节奏。
关键配置项必须调整:
- 禁用
testOnBorrow(UCP)或connection-test-query(HikariCP),否则池子会在TAF重建连接前就把“stale connection”踢掉 - 把
connection-timeout设为≥30秒,给新主库监听注册留出时间(ALTER SYSTEM REGISTER默认60秒刷新,但实际常3~5秒就可见) - UCP必须显式调用
setFastConnectionFailoverEnabled(true),否则FCF事件不会被消费,TAF感知不到Broker发来的角色变更通知 - 不要用
OracleDataSource.setFailoverEnabled(true)——ojdbc8+ 已废弃该方法,调了也白调
最易被忽略的一点:FSFO切换后,新主库监听可能还没完成服务注册。此时连接池若以毫秒级频率重试,全量失败后直接抛异常,而不是等DELAY后重试。这个窗口期必须靠延长超时+关闭预检来兜底。


















