TAF配置不生效主因是TNSNAMES.ORA中未正确定义FAILOVER_MODE参数,需显式设置TYPE(SESSION/SELECT)、METHOD(BASIC)、RETRIES、DELAY及ADDRESS_LIST顺序;srvctl服务需配合DB_ROLE_CHANGE触发器或Broker手动启用,JDBC须配置TnsAdmin并使用≥12.1驱动。
Oracle客户端TAF配置不生效,连接没切换?检查TNSNAMES.ORA里FAILOVER_MODE是否写对了
很多人配完data guard后发现主库挂了,应用连不上——不是taf没起作用,而是客户端根本没按taf方式发起连接。关键在tnsnames.ora中服务名定义里必须显式声明failover_mode,且参数值要匹配实际需求。
常见错误现象:ORA-01033: ORACLE initialization or shutdown in progress或直接超时,而不是自动切到备库;用tnsping能通,但SQL*Plus连不上主库时没触发重连。
-
TYPE必须是SELECT或SESSION(前者只对查询生效,后者才支持会话级故障转移) -
METHOD推荐用BASIC(客户端直连,不依赖监听器转发),PRECONNECT虽快但占资源、难调试 -
RETRIES和DELAY别设太激进(比如RETRIES=2 DELAY=1),容易在主库瞬断时误判为宕机 - 确认
ADDRESS_LIST里至少有两个地址,且顺序合理:主库放前面,备库放后面
示例片段:
DG_SERVICE =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = primary-host)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = standby-host)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = orcl_dg)
(FAILOVER_MODE =
(TYPE = SESSION)
(METHOD = BASIC)
(RETRIES = 3)
(DELAY = 5)
)
)
)
Service Trigger没触发,srvctl add service加的service状态一直是OFFLINE
Data Guard里靠srvctl管理的服务(如orcl_app)不会自动随角色切换而启停,必须配合Broker或自定义脚本监听DB_ROLE_CHANGE事件。否则即使主备切换完成,服务仍卡在原节点,客户端连的是空壳。
使用场景:RAC+DG环境,想让应用连接始终落在当前PRIMARY上,且不改连接串。
- 必须用
srvctl add service -r指定首选实例(即当前主库所在实例),并用-a指定可用实例(备库实例可选,但仅当启用Fast-Start Failover时才有意义) - 服务启动后,检查
crsctl stat res -t | grep service,若状态非ONLINE,大概率是数据库没注册该service——执行ALTER SYSTEM REGISTER或等监听器自动刷新(默认60秒) - Broker开启时,
ENABLE服务后需手动EDIT DATABASE ... SET PROPERTY ServiceName=...,否则Broker不接管 - 不要依赖
START命令一次启动:先srvctl start service,再srvctl enable service,顺序反了会失效
Java应用连TAF服务,事务中断后不重试,Connection.isValid()返回true但执行SQL报ORA-03113
JDBC驱动默认不解析TAF元数据,即使TNS配置正确,Connection对象也不知道自己已漂移到新实例。结果就是连接看似活着,一发SQL就崩——因为旧事务上下文在原实例上已丢失。
性能影响:开启TAF感知会轻微增加初次连接开销,但避免了应用层反复捕获异常再重连的逻辑复杂度。
- 必须在JDBC URL里加
oracle.jdbc.TnsAdmin指向TNSNAMES.ORA所在目录,否则驱动读不到FAILOVER_MODE - 驱动版本要≥12.1(11g部分版本对
BASIC模式支持不全),建议用ojdbc8.jar及以上 - 代码里不能依赖
Connection.isClosed()判断连接有效性,得用isValid(2)(带超时)或直接捕获SQLException中getErrorCode()是否为3113/3114 - Spring Boot项目需额外配置
spring.datasource.hikari.data-source-properties.oracle.jdbc.TnsAdmin=/path/to/tns
Broker配置了AUTO_START,但角色切换后service没自动拉起
Broker管的是数据库实例启停和角色转换,不负责service生命周期。哪怕你在DGMGRL里执行ENABLE CONFIGURATION,也不会自动调用srvctl start service。这是最容易被忽略的断点。
为什么这样做:Oracle把“高可用”拆成两层——Broker保数据库存活,service管理器保应用入口存活。二者解耦,但也意味着必须手动桥接。
- 最稳方案是写
DB_ROLE_CHANGE触发器,在数据库内捕获角色变更后调用DBMS_SCHEDULER执行srvctl命令(注意权限:需OSDBA组+ORACLE_HOME环境变量) - 避免用
crontab轮询v$database.database_role,延迟高、易冲突 - 如果用Broker的
Fast-Start Failover,必须在Observer机器上部署FSFO脚本,并在Enable Fast-Start Failover前确认ServiceName属性已绑定到PrimaryRole - 检查
srvctl config service输出里的Management Policy是否为AUTOMATIC,否则即使数据库启动,service也不会自启
复杂点在于Broker、CRS、TNS、JDBC四层各自维护一套状态,任何一层没对齐,漂移就断在半路。尤其FAILOVER_MODE和srvctl之间没有自动联动,得靠人来补这根线。










