Oracle Data Guard 本身不提供客户端连接自动切换能力,TAF必须由客户端主动触发,且依赖服务端三要素齐备:TAF服务、角色感知存储过程、数据库启动/角色变更触发器,缺一不可,否则客户端报IO Error: Connection reset。

Oracle Data Guard 本身不提供客户端连接自动切换能力,TAF(Transparent Application Failover)必须由客户端主动触发,且依赖服务端三要素齐备:TAF服务、角色感知存储过程、数据库启动/角色变更触发器。缺一不可,否则客户端看到的仍是 IO Error: Connection reset。
DBMS_SERVICE.CREATE_SERVICE 配置要点
服务必须在主库创建,DG会同步到备库,但服务默认不启动——这是最容易忽略的前提。
-
service_name和network_name要区分清楚:service_name是 DBA 管理名(如'dg_taf_crmdb'),network_name是客户端tnsnames.ora中SERVICE_NAME字段实际使用的值(如'taf_crmdb') -
failover_type选'SELECT'仅对带游标保持(WITH HOLD)的查询有效;业务含 DML 或无状态查询,必须用'SESSION' -
failover_retries和failover_delay要匹配应用容忍窗口:比如设置RETRIES=180、DELAY=5,意味着最长等待 15 分钟,期间不断重连,不是“一次失败就报错”
存储过程 + 触发器必须成对存在
只建服务不启停,等于没配;只建存储过程不挂触发器,角色切换后服务状态不会自动更新。
- 存储过程里必须用
V$DATABASE.DATABASE_ROLE判断,不能查V$INSTANCE或靠实例名硬编码 - 触发器类型必须是
AFTER STARTUP OR DB_ROLE_CHANGE ON DATABASE,DB_ROLE_CHANGE是 DG 切换时真正触发的关键事件,AFTER STARTUP保证实例重启后服务状态正确 - 触发器和存储过程都必须在
SYS用户下创建,普通用户无权限监听角色变更事件
客户端 tnsnames.ora 的 FAILOVER_MODE 必须与服务端对齐
客户端配置不是可选步骤,而是 TAF 生效的最后闸门。OCI 连接才支持完整 TAF 行为,JDBC Thin Driver 不触发 TAF 回调。
-
FAILOVER_MODE=(TYPE=SESSION)(METHOD=BASIC)(RETRIES=180)(DELAY=5)中的参数值,必须和DBMS_SERVICE.CREATE_SERVICE里传入的failover_type、failover_method、failover_retries、failover_delay完全一致,否则服务端策略不生效 - 地址列表里要同时写主库和备库的
ADDRESS,且LOAD_BALANCE=NO(TAF 场景禁用负载均衡,否则连接可能打到非当前主库) - Java 应用若用 UCP 或 HikariCP,需显式关闭连接池的“验证查询”干扰,避免在故障窗口期误判节点存活
常见失效场景与验证点
TAF 失效往往不是配置错,而是某个环节被绕过或未激活。
- 检查服务是否真在运行:
SELECT NAME, FAILOVER_TYPE, FAILOVER_METHOD FROM V$ACTIVE_SERVICES;—— 切换后这里必须有对应服务名且状态为 ACTIVE - 确认触发器已启用:
SELECT TRIGGER_NAME, STATUS FROM DBA_TRIGGERS WHERE TRIGGER_NAME = 'DG_TAF_TRG_STARTUP';,状态必须是ENABLED - OCI 客户端连接时加
sqlplus /@dg_taf后执行SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME') FROM DUAL;,返回值应为服务端定义的network_name,不是service_names参数值 - 备库切为主库后,原主库实例若未 shutdown,其上的 TAF 服务仍可能被客户端连上——这不是 bug,是设计使然,需靠网络层隔离或防火墙阻断











