必须配静态监听,因备库mount状态下pmon不注册服务,动态监听无法识别;静态监听通过listener.ora中sid_list_listener强制声明global_dbname为_dgmgrl,确保dgmgrl和broker可连接。

必须配静态监听,否则备库 mount 状态下无法被主库或 DGMGRL 识别,lsnrctl status 里服务状态会是 UNKNOWN,DG 切换、Broker 连接全失败。
为什么动态监听在 DG 场景下不可靠
Oracle 实例默认用 PMON 动态向监听注册服务,但这个动作只在数据库 OPEN 状态下触发。Data Guard 备库正常运行时处于 MOUNT 状态 —— 此时 PMON 不注册,监听里看不到该实例。静态监听则绕过 PMON,靠 listener.ora 里的 SID_LIST_LISTENER 强制声明,不管库是 MOUNT 还是 OPEN 都能被发现。
常见错误现象:
-
lsnrctl status显示服务状态为UNKNOWN(不是READY) - DGMGRL 报错:
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor - 主库
ALTER SYSTEM SWITCH LOGFILE后,备库SELECT MAX(SEQUENCE#) FROM V$ARCHIVED_LOG查不到新归档
SID_LIST_LISTENER 必须包含 _DGMGRL 服务名
DG Broker(dgmgrl)连接主备库时,默认尝试连接 db_unique_name_DGMGRL 这个服务名。如果静态监听没配这个条目,Broker 就连不上,后续所有 EDIT DATABASE、SWITCHOVER 操作都会卡住。
实操要点:
- 主库
SID_LIST_LISTENER中至少要有一条SID_DESC,其GLOBAL_DBNAME设为<db_unique_name>_DGMGRL</db_unique_name>(如test19_DGMGRL) - 同一份
SID_LIST_LISTENER可同时定义多个SID_DESC:一个给_DGMGRL,一个给普通业务连接(GLOBAL_DBNAME = <db_unique_name></db_unique_name>) -
SID_NAME必须与实际实例名一致(即INSTANCE_NAME,通常等于ORACLE_SID) -
ORACLE_HOME路径必须绝对准确,不能用变量(如$ORACLE_HOME),必须展开成真实路径(如/u01/app/oracle/product/19.3.0/db_1)
示例片段:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = test19_DGMGRL)
(ORACLE_HOME = /u01/app/oracle/product/19.3.0/db_1)
(SID_NAME = test19)
)
(SID_DESC =
(GLOBAL_DBNAME = test19)
(ORACLE_HOME = /u01/app/oracle/product/19.3.0/db_1)
(SID_NAME = test19)
)
)
lsnrctl reload 后一定要验证状态
改完 listener.ora 不能只执行 lsnrctl reload 就完事。reload 不会重启监听进程,只重读配置,但旧的注册信息可能残留。必须确认新服务已加载且状态正确。
验证步骤:
- 执行
lsnrctl status,检查输出中是否有你刚配的GLOBAL_DBNAME(如test19_DGMGRL),且对应实例状态为UNKNOWN(这是静态监听的正常表现,不是错误) - 用
tnsping测试连通性:tnsping test19_DGMGRL应返回OK - 从另一台机器(如主库)用
sqlplus sys@<tns_alias> as sysdba</tns_alias>尝试连接,确保能进 SQL*Plus(哪怕只是报ORA-01033,说明网络和监听层通了) - 若用 Broker,登录
dgmgrl后执行show configuration,应不再报连接超时
最容易被忽略的是:静态监听生效后,GLOBAL_DBNAME 和 SID_NAME 的大小写必须与数据库实际参数完全一致(Oracle 默认区分),且 tnsnames.ora 里引用的服务名必须和 GLOBAL_DBNAME 完全匹配 —— 差一个下划线或大小写,Broker 就连不上。











