必须同时指定-r(preferred)和-a(available),二者不能相同且须为真实实例名;漏写或写反将导致服务无法故障转移。

服务名配置时 preferred 和 available 实例写反了
这是最常见也最容易被忽略的根源。比如你本意是让应用优先连 crmdb1,故障时切到 crmdb2,但执行 srvctl add service 时把 -r crmdb2 -a crmdb1 写成了 -r crmdb2 -a crmdb2,或者干脆漏掉 -a 参数——这时服务就只绑定了一个实例,根本不会故障转移。
-
srvctl add service必须同时指定-r(preferred)和-a(available),两者不能相同,且必须是集群中真实存在的实例名 - 确认实例名是否大小写敏感:
srvctl config database -d racdb输出的实例名要一字不差地用在服务命令里 - 添加后立刻用
srvctl config service -d racdb -s crm62验证配置,重点看Preferred instances和Available instances两行
客户端连接字符串没启用 TAF 或配置错误
服务端配对了,但客户端没告诉 Oracle “我需要故障切换”,那连接还是死盯 preferred 节点。TAF(Transparent Application Failover)不是默认开启的,得显式声明。
- tnsnames.ora 里对应的服务条目必须包含
(FAILOVER=ON)和(FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC)(RETRIES=180)(DELAY=5)) - 如果用 JDBC,URL 中需加
&oracle.jdbc.fanEnabled=true,且依赖 Oracle JDBC driver 12cR2 及以上版本 - 验证是否生效:在连接后执行
SELECT sys_context('USERENV','INSTANCE_NAME') FROM DUAL,然后手动 kill 掉当前实例,再查一次——结果应变成另一个节点名
集群资源状态异常导致服务无法迁移
即使服务配置正确、客户端也启用了 TAF,如果目标节点上的 CRS 资源没在线,服务也迁不过去。典型表现是:srvctl status service 显示服务只在一个节点 RUNNING,另一个节点显示 OFFLINE 或 INTERMEDIATE。
- 先查整体状态:
crsctl status resource -t,重点关注ora.<service_name>.svc</service_name>和它依赖的ora.<instance_name>.inst</instance_name> - 常见卡点:目标节点 ASM 实例没起来(
ora.asm状态不是 ONLINE)、磁盘组没 mount(ora.DATA.dg是 OFFLINE)、监听器异常(ora.LISTENER.lsnr没 ONLINE) - 不要直接重启服务,先用
srvctl start instance -d racdb -i crmdb2手动拉起实例,再观察服务是否自动 failover
负载均衡策略干扰了故障切换逻辑
Oracle 默认用 LOAD_BALANCE=ON 把新连接均匀分发到所有 UP 的实例上,但这和 TAF 的故障切换是两套机制。如果 LOAD_BALANCE 和 FAILOVER 同时开,可能造成连接刚建立就切走,或重试时连到错误节点。
- 业务明确要求“主备模式”(即 99% 流量走 preferred,只在故障时切)时,tnsnames.ora 中务必去掉
(LOAD_BALANCE=ON) - 如果确实需要读写分离+故障切换,建议拆成两个 service:一个带
LOAD_BALANCE=ON用于只读,一个带FAILOVER=ON且无 load balance 用于写操作 - 注意:SCAN listener 默认启用负载均衡,所以单靠 SCAN 地址无法实现 strict preferred-instance 行为,必须用具体 VIP 或 host 名定义 service











