主库和备库的 tnsnames.ora 必须双向定义对方 VIP 与静态服务名,listener.ora 需显式配置 SID_NAME 和 GLOBAL_DBNAME 并保持与 tnsnames.ora 中 SERVICE_NAME 一致,local_listener 参数须指向本机 VIP,且 VIP、监听、实例注册三者必须闭环。
主库和备库的 tnsnames.ora 必须双向定义对方的 VIP + 静态服务名
很多人只在主库配备库、不配回主库,结果 switchover 一执行就卡在连接备库实例上。根本原因是 oracle 在切换过程中会主动用本地 tnsnames.ora 解析目标库,而解析失败直接报 ora-12154 或 ora-12514。
实操建议:
- 主库
$ORACLE_HOME/network/admin/tnsnames.ora中必须有指向备库 VIP 的条目,服务名用静态注册名(如STANDBY_DG),不是数据库名或 DB_UNIQUE_NAME - 备库同理,必须有指向主库 VIP 的条目,服务名保持一致(如也叫
PRIMARY_DG) - 两个 VIP 必须能互相 ping 通,且对应监听器监听的是
1521(或其他统一端口),不能一个用1521、一个用1522 - 服务名别图省事叫
ORCL—— 容易和动态注册冲突;推荐带后缀,比如PRIMARY_DG/STANDBY_DG
listener.ora 里静态注册服务名必须显式写 SID_NAME 和 GLOBAL_DBNAME
只写 SID_LIST 不够,Oracle Data Guard 在角色切换时依赖 GLOBAL_DBNAME 匹配服务名。如果这里写错,lsnrctl status 看起来正常,但 CONNECT / AS SYSDBA 连过去发现实例没注册上,报 ORA-12514: TNS:listener does not currently know of service requested in connect descriptor。
实操建议:
- 每个节点的
$ORACLE_HOME/network/admin/listener.ora中,静态注册段必须包含:SID_DESC = (SID_NAME = <code>ORCL</code>) (ORACLE_HOME = <code>/u01/app/oracle/product/19c/dbhome_1</code>) (GLOBAL_DBNAME = <code>PRIMARY_DG</code>)
-
GLOBAL_DBNAME值要和tnsnames.ora里SERVICE_NAME完全一致(大小写敏感) - 改完
listener.ora后必须执行lsnrctl reload,不是stop/start—— 否则连接可能中断
使用 SCAN VIP 时,tnsnames.ora 不能混用 VIP 和 SCAN
有些人在 RAC 环境下误把主库配成 SCAN、备库配成单节点 VIP,结果 DGMGRL 检查状态时反复报 ORA-12545: Connect failed because target host or object does not exist。SCAN 是为客户端负载均衡设计的,Data Guard 内部通信要求确定性路由,必须用 VIP。
实操建议:
- 无论主备是否为 RAC,只要用了 Data Guard,所有
tnsnames.ora条目中的HOST必须填对应节点的 VIP(如192.168.10.11),不是 SCAN IP,也不是物理 IP - 确认 VIP 已绑定到网卡且
ifconfig可见;RAC 环境下还要检查crsctl stat res -t | grep vip是否 ONLINE - 测试连通性不要只用
tnsping,得实际sqlplus sys@PRIMARY_DG as sysdba——tnsping成功不代表服务名被监听器识别
备库开启 FORCE LOGGING 和 ARCHIVELOG 后,监听仍连不上?查 local_listener 参数
即使 tnsnames.ora 和 listener.ora 全对,备库启动后也可能无法被主库识别,现象是 DGMGRL SHOW DATABASE VERBOSITY 显示 STATUS = ORA-12514。常见原因是备库的 local_listener 指向了空值或错误地址,导致动态注册覆盖了静态注册。
实操建议:
- 在备库执行:
SHOW PARAMETER local_listener—— 如果返回空或指向localhost,立刻改掉:ALTER SYSTEM SET local_listener='(ADDRESS=(PROTOCOL=TCP)(HOST=<code>standby-vip)(PORT=1521))' SCOPE=BOTH; - 改完立即
ALTER SYSTEM REGISTER;,再查lsnrctl services,确认输出里有该GLOBAL_DBNAME对应的服务行 - 特别注意:主库和备库的
local_listener必须分别指向各自 VIP,不能共用同一个值
switchover 就会停在第一步。










