DG切换必须依赖静态监听,因动态注册有延迟且需实例处于MOUNT/OPEN状态,而切换时新主库刚启动、PMON尚未完成注册;静态监听通过SID_LIST_LISTENER预加载GLOBAL_DBNAME,确保监听器即时识别服务,避免ORA-12514或ORA-16664。

切库后客户端连不上,ORA-12514 或 ORA-16664 频发,八成是静态监听没配对——Data Guard Broker 和物理备库启动后,若监听器压根不知道这个实例存在,切换瞬间就失联。
为什么 DG 切换必须依赖静态监听
动态注册靠 PMON 进程向监听器上报服务信息,但这个过程有延迟,且要求数据库已 OPEN 或至少 MOUNT。而 DG 切换(尤其是 Switchover)过程中,原主库可能已关闭、新主库刚从 MOUNT 启动,PMON 尚未完成注册,监听器查无此服务,客户端连接直接失败。
静态监听则不同:SID_LIST_LISTENER 是监听器启动时就加载的“白名单”,不依赖数据库状态。只要监听器活着,GLOBAL_DBNAME 对应的服务就可被识别和转发。
- Broker 的
DGMGRL连接(如CONNECT sys@orcl_standby)必须能解析到orcl_standby_DGMGRL这个服务名,否则报ORA-16664 - 客户端 TNS 连接串里的
SERVICE_NAME必须与静态注册的GLOBAL_DBNAME完全一致(含域名后缀) - RAC 环境下,每个节点监听器都需单独配置对应本节点的
SID_DESC,不能只配一个
listener.ora 中 SID_LIST_LISTENER 的关键写法
SID_LIST_LISTENER 不是可选项,是静态注册的唯一入口。漏掉或拼错任一字段,lsnrctl status 里就看不到服务。
必须包含且仅包含以下三要素,顺序无关但大小写敏感:
-
SID_NAME:必须与v$database.name或SELECT instance_name FROM v$instance一致(注意不是db_name) -
ORACLE_HOME:路径必须精确到末尾无斜杠,且所有节点保持一致(RAC 多节点时尤其注意) -
GLOBAL_DBNAME:这是最易错的点——DG 场景下它必须是db_unique_name_DGMGRL.db_domain(Broker 要求)或db_unique_name(手动管理时),不能填service_name或db_name
示例(主库为 rac_primary,备库为 rac_standby,域名为 us.oracle.com):
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = rac_primary.us.oracle.com)
(ORACLE_HOME = /u01/app/oracle/product/19c/dbhome_1)
(SID_NAME = rac_primary1)
)
(SID_DESC =
(GLOBAL_DBNAME = rac_standby_DGMGRL.us.oracle.com)
(ORACLE_HOME = /u01/app/oracle/product/19c/dbhome_1)
(SID_NAME = rac_standby)
)
)
reload 之后必须验证的三件事
改完 listener.ora,执行 lsnrctl reload 只是第一步。不验证等于没配。
- 运行
lsnrctl status,检查输出中是否出现你配置的GLOBAL_DBNAME,且状态为READY(不是UNKNOWN) - 用
tnsping测试该服务名能否通:例如tnsping rac_standby_DGMGRL,返回 “OK” 才算网络层通 - 用
sqlplus /@rac_standby_DGMGRL(或带密码)尝试实际连接,确认能进 SQL*Plus,而非卡在认证阶段
常见坑:tnsnames.ora 里定义的 SERVICE_NAME 和监听器里 GLOBAL_DBNAME 不一致;sqlnet.ora 中 NAMES.DIRECTORY_PATH 没包含 TNSNAMES,导致本地解析失败;监听器日志 $ORACLE_HOME/network/log/listener.log 里有 TNS-12505 报错,说明 SID_NAME 与实例实际名称对不上。
DG Broker 场景下 GLOBAL_DBNAME 的命名规则
Broker 不接受任意 GLOBAL_DBNAME。它强制要求用于管理连接的服务名必须带 _DGMGRL 后缀,且域名必须匹配 DB_DOMAIN 参数值。
- 查当前
DB_UNIQUE_NAME和DB_DOMAIN:SELECT db_unique_name, value FROM v$parameter WHERE name = 'db_domain'; - 计算出完整服务名:
db_unique_name+_DGMGRL+.+db_domain(如orcl_standby_DGMGRL.us.oracle.com) - 这个完整字符串必须同时出现在:
listener.ora的GLOBAL_DBNAME、tnsnames.ora的SERVICE_NAME、以及DGMGRL的CONNECT IDENTIFIER
Broker 启动后会主动探测这个服务名,一旦发现监听器返回 UNKNOWN 或超时,就会拒绝启用配置,后续所有 ENABLE CONFIGURATION 均失败。这不是权限或密码问题,纯属名字没对上。


















