oracle rac高可用依赖客户端连接串、服务端注册及网络策略协同,而非连接串本身;service_name须为跨节点服务名(如orclpdb),不可用instance_name;scan需dns返回3个a记录并正确注册,ora-12514多因scan监听器未注册服务所致。

Oracle RAC连接串本身不决定高可用性,真正起作用的是客户端配置、服务端服务注册方式和底层网络策略。盲目改连接串反而容易引入单点故障或连接超时问题。
tnsnames.ora 中 SERVICE_NAME 和 INSTANCE_NAME 的区别必须分清
很多团队把 SERVICE_NAME 写成具体实例名(如 rac1),这是典型错误——这会让连接直连单个节点,完全绕过RAC的负载均衡和故障转移能力。
-
SERVICE_NAME应指向数据库服务名(如orclpdb),该服务由srvctl add service创建并跨所有节点注册 -
INSTANCE_NAME是内部参数,不应出现在客户端连接串中;它只在单实例场景或调试时使用 - RAC服务默认启用
LOAD_BALANCE=on和FAILOVER=on,但前提是连接串里用的是服务名,不是实例名
SCAN listener 配置错误会导致连接失败率飙升
SCAN(Single Client Access Name)是RAC高可用的基石,但它的 DNS 解析和监听器状态极易出问题。
- 确保 DNS 返回 3 个 A 记录(对应 3 个 SCAN VIP),且每个 SCAN VIP 绑定到不同节点的物理网卡
- 检查
lsnrctl status LISTENER_SCAN1,确认 SCAN listener 正在运行且注册了所有实例 - 如果用 hosts 文件模拟 SCAN,必须为每个 SCAN IP 配置独立条目,不能只写一个 IP —— 否则客户端无法实现轮询和故障转移
- 常见错误:
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor,基本都是 SCAN listener 没注册服务或监听器未启动
Java / PHP / .NET 客户端必须显式启用连接池的 RAC 感知能力
即使连接串写对了,如果应用层连接池(如 HikariCP、UCP、ODP.NET)没开启 RAC 支持,依然会退化为单节点行为。
- Oracle UCP(Universal Connection Pool)需设置
connectionPool.setONSConfiguration("nodes=rac-node1:6200,rac-node2:6200")并启用enableImplicitConnectionCache=true - Java JDBC URL 示例:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=rac-scan)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orclpdb)(FAILOVER_MODE=(TYPE=SESSION)(METHOD=BASIC)))) - PHP OCI8 需调用
oci_connect()时传入完整描述符,并确保oci_new_connect()不被滥用(它不复用连接池) - .NET ODP.NET Core 必须启用
EnableOdpNetCoreFeatures = true和ConnectionTimeout=30,否则首次连接失败后不会自动重试其他节点
连接超时与重试参数不匹配会放大故障影响
RAC 故障转移不是瞬时的,客户端必须给 Clusterware 和 SCAN 足够时间完成实例探测和重路由。
-
CONNECT_TIMEOUT=30(不是 10)—— 太短会导致连接在故障转移完成前就报错 -
RETRY_COUNT=3+RETRY_DELAY=5—— 避免瞬间重试压垮剩余节点 - 禁用
ENABLE=BROKEN(旧版参数),它会跳过健康检查直接发请求,导致连接到已宕机但尚未被 Clusterware 清理的实例 - 关键但常被忽略:
SQLNET.EXPIRE_TIME=0在服务器端配置,否则空闲连接可能被中间设备(如防火墙)静默断开,而客户端无感知
最易被忽略的其实是服务注册粒度——一个业务模块对应一个专用服务名(比如 report_svc),并绑定到指定节点组,而不是所有应用共用 orclpdb。这样既能隔离负载,又能让故障影响范围可控。RAC 的高可用不是靠“连得上”,而是靠“连得对、切得快、不扩散”。











