必须配静态监听,因备库mount状态下pmon不注册服务,动态监听无法识别;需在listener.ora中用sid_list_listener强制声明global_dbname为_dgmgrl,确保dgmgrl、broker及日志传输正常。

Oracle 19c 的 Data Guard 环境中,必须配静态监听,动态监听不能替代它。备库处于 MOUNT 状态时,PMON 不向监听注册服务,动态监听里根本看不到实例;而 DGMGRL、Broker 切换、日志传输等关键操作全依赖监听能“看见”备库——所以静态监听不是可选项,是启动 DG 的前提。
为什么不能只靠动态监听?
Oracle 实例默认靠 PMON 进程在 OPEN 状态下自动向监听注册服务名(如 DB_UNIQUE_NAME)。但物理备库正常运行时始终是 MOUNT 状态,PMON 不触发注册,监听里查不到该实例,lsnrctl status 中对应服务状态显示为 UNKNOWN 而非 READY。
此时哪怕 tnsping 通、端口可达,sqlplus sys/xxx@DB2 as sysdba 仍会报:
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
这个错误不是网络问题,是监听压根没加载你的实例。动态监听在此场景下完全失效。
SID_LIST_LISTENER 必须包含 _DGMGRL 服务名
DGMGRL 默认连接主备库时,用的是 <db_unique_name>_DGMGRL</db_unique_name> 这个服务名(例如主库 prod19_DGMGRL,备库 prod19_stby_DGMGRL)。如果 listener.ora 里没显式声明这个 GLOBAL_DBNAME,Broker 就连不上,后续所有 EDIT DATABASE、SWITCHOVER 全卡死。
实操要点:
-
SID_DESC中的GLOBAL_DBNAME必须严格等于<db_unique_name>_DGMGRL</db_unique_name>(注意大小写和下划线) -
SID_NAME必须与实际实例名一致(即V$INSTANCE.INSTANCE_NAME,通常等于ORACLE_SID) -
ORACLE_HOME必须写绝对路径,不能用$ORACLE_HOME变量 - 一个
SID_LIST_LISTENER可同时定义多个SID_DESC:一个给_DGMGRL,一个给普通业务连接(如GLOBAL_DBNAME = prod19)
示例(主库):
SID_LIST_LISTENER = (SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = prod19_DGMGRL)
(ORACLE_HOME = /u01/app/oracle/product/19.3.0/db_1)
(SID_NAME = prod19)
)
(SID_DESC =
(GLOBAL_DBNAME = prod19)
(ORACLE_HOME = /u01/app/oracle/product/19.3.0/db_1)
(SID_NAME = prod19)
)
)
reload 不等于重启,status 验证不能跳过
改完 listener.ora 后执行 lsnrctl reload,只是重读配置,不会清空旧的注册缓存。旧的 UNKNOWN 条目可能还在,导致你以为配好了,其实 Broker 还连不上。
正确操作顺序:
- 先
lsnrctl stop - 再
lsnrctl start - 最后用
lsnrctl status检查输出中是否出现两条SERVICE_NAME:一条是<db_unique_name>_DGMGRL</db_unique_name>,一条是<db_unique_name></db_unique_name>,且状态都为READY - 额外验证:
tnsping <tns_alias_for_dgmgrl></tns_alias_for_dgmgrl>+dgmgrl sys/xxx@<tns_alias_for_dgmgrl></tns_alias_for_dgmgrl>
特别注意:listener.ora 文件中不能有制表符(TAB),Oracle 解析器会静默失败,导致 SID_LIST_LISTENER 不生效——用 cat -A listener.ora 检查是否有 ^I。
动态监听还能用吗?可以,但仅限 OPEN 状态下的辅助用途
动态监听不是废的,它在主库 OPEN、或备库临时 OPEN READ ONLY 时能自动注册业务服务名(如 prod19),方便应用连接。但它对 DG 核心流程无贡献。
如果你把备库临时 OPEN READ ONLY 做报表查询,动态监听这时才起作用;一旦切回 MOUNT,它立刻“失联”。别指望它扛 DG 的活。
真正容易被忽略的点是:ORACLE_HOME 路径写错、GLOBAL_DBNAME 拼错(比如漏了 _DGMGRL)、lsnrctl reload 后没验证 status 输出——这三处出错,DG 后续所有操作都会在第一步就失败,而且错误信息不指向根本原因。











