动态注册与静态注册:监听器里的两本账
同一个库,
lsnrctl services里有时看到 READY,有时看到 UNKNOWN;数据库没起来的时候,有的环境连得上监听(然后报 ORA-01034),有的环境直接 ORA-12514。这些差异都指向同一件事:监听器手里的服务信息,到底是数据库自己报上来的(动态注册),还是配置文件里写死的(静态注册)。这篇把两本账讲清楚,什么时候用哪本。
文章目录
- 动态注册与静态注册:监听器里的两本账
- 一、先看现象:READY 和 UNKNOWN
- 二、动态注册:实例进程主动来登记
- 原理
- 相关参数与操作
- 三、静态注册:listener.ora 里写死的账
- 配置
- 特性
- 四、对比表
- 五、什么时候必须用静态注册
- 六、各自的坑
- 七、生产建议
一、先看现象:READY 和 UNKNOWN
$ lsnrctl services Services Summary... Service "orcl" contains 2 instance(s). Instance "orcl", status READY, has 1 handler(s) for this service... Instance "orcl", status UNKNOWN, has 1 handler(s) for this service...READY:动态注册。数据库实例的注册进程(11g 及以前是 PMON,12c 起是 LREG)亲自来登记的,“我这个实例活着,服务名叫 orcl,能接活”UNKNOWN:静态注册。listener.ora 里写死的条目,监听器只负责往那个 ORACLE_HOME 转发,实例死活它不知道
两条并存不是配置冲突,是正常且推荐的状态。
二、动态注册:实例进程主动来登记
原理
实例启动后,由注册进程向监听器登记自己的信息(旧版本 PMON 约每60 秒轮询一次,12c 的 LREG 在实例启动及服务变更时登记):
- 登记内容:实例名(instance_name)、服务名(service_names)、当前状态、负载信息
- 登记目标:默认是本机 1521 端口的监听器;由
local_listener参数控制 - 关键特性:实例一关闭,注册信息随之消失——监听器立刻"忘记"这个实例
这就解释了几个日常现象:
库刚
startup完马上连,偶尔报 12514——注册还没完成(旧版本要等 PMON 下一个 60 秒轮询)。手动立即注册:ALTERSYSTEM REGISTER;监听器重启后,
lsnrctl status里短暂看不到服务——同样在等实例重新注册
相关参数与操作
-- 实例叫什么、对外提供什么服务SHOWPARAMETER instance_nameSHOWPARAMETER service_names-- 注册到哪个监听器(默认空 = 本机1521)SHOWPARAMETER local_listener-- 多端口/非常规端口时,明确指定注册目标ALTERSYSTEMSETlocal_listener='(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.10)(PORT=1522))'SCOPE=BOTH;ALTERSYSTEM REGISTER;PDB 的服务也是动态注册的:PDB open 时注册,closed 时消失:
ALTERPLUGGABLEDATABASEhrpdbOPEN;-- 服务注册ALTERPLUGGABLEDATABASEhrpdbCLOSE;-- 服务注销三、静态注册:listener.ora 里写死的账
配置
编辑$ORACLE_HOME/network/admin/listener.ora:
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = orcl) (ORACLE_HOME = /u01/app/oracle/product/19.0.0/dbhome_1) (SID_NAME = orcl) ) ) LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.10)(PORT = 1521)) ) )字段说明:
SID_NAME:实例名,连接串里SID=方式用的名字GLOBAL_DBNAME:对外服务名,SERVICE_NAME=方式用的名字,可以和动态注册的重合,也可以另起一个ORACLE_HOME:监听器转发连接时要用它去 spawn/bequeath 服务器进程,路径必须准确,写错监听器可能起不来或无法派生进程
改完重载:
lsnrctl reload lsnrctl services特性
静态条目写在文件里,不依赖数据库进程:
- 库 shutdown 后,
lsnrctl services里 UNKNOWN 条目依然在 - 客户端连过来,监听器照常接收转发,然后才发现实例没起,报
ORA-01034: ORACLE not available - 反过来说,UNKNOWN 状态不提供实例死活、负载的任何信息——它只是个静态的门牌
四、对比表
| 对比项 | 动态注册 | 静态注册 |
|---|---|---|
| 谁登记 | 实例的注册进程(旧版 PMON,12c 起 LREG) | DBA 写在 listener.ora |
| status 显示 | READY(含 BLOCKED 等真实状态) | UNKNOWN |
| 库关闭后 | 条目消失,连接报 12514 | 条目仍在,连接报 01034 |
| 反映实例状态 | 是(READY/READY WITH SERVICES/BLOCKED) | 否 |
| 支持负载信息 | 是(connect-time failover 依据) | 否 |
| 配置成本 | 零配置(默认端口时) | 要维护 SID、ORACLE_HOME |
| 注册延迟 | 旧版最多 60 秒(可 ALTER SYSTEM REGISTER) | reload 立即 |
| 库没起时能否连接 | 不能 | 能(连到实例后再报错) |
五、什么时候必须用静态注册
场景一:数据库还没起来,但要远程连进去
典型是远程启动实例和 RMAN 恢复。实例 nomount 阶段:
# 在 DBA 的机器上,远程连一个只有 spfile、还没起来的实例sqlplus sys/密码@192.168.1.20:1521/orcl as sysdba SQL>STARTUP NOMOUNT;没有静态注册,这条 sqlplus 直接 12514——监听器不知道 orcl 的存在。有了静态注册,连接被转发到实例(哪怕它只到 nomount),DBA 才有机会远程把它拉起来。这在服务器没有图形/SSH 不便、只能走网络的恢复场景里是唯一的路。
场景二:Data Guard 环境
DG 的配置里,静态监听接近标配:
- duplicate 搭建 DG:目标端实例只到 nomount,RMAN 要从主库通过网络连到这个"半死不活"的实例,靠的就是静态注册
- 主备切换(switchover/failover):切换过程中实例会重启,动态注册随之消失又重建;客户端和 FAL 传输需要一直有稳定的连接入口
- 备库 mounted 状态下动态注册显示
READY但带 blocked 标记(只读应用除外),行为容易让排查变乱,静态条目稳定可控
DG 单边静态监听示例:
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = orcl_primary) (ORACLE_HOME = /u01/app/oracle/product/19.0.0/dbhome_1) (SID_NAME = orcl) ) (SID_DESC = (GLOBAL_DBNAME = orcl_standby) (ORACLE_HOME = /u01/app/oracle/product/19.0.0/dbhome_1) (SID_NAME = orcl) ) )同一个 SID 挂两个 GLOBAL_DBNAME,客户端用不同服务名区分角色,比依赖动态注册的状态直观得多。
场景三:希望"门牌永远在"的任意场景
比如要求任何时候lsnrctl services都能看到实例条目(巡检脚本按条目数报警),静态注册能保证账面稳定。
六、各自的坑
动态注册的坑:
local_listener指错端口/指了旧主机名,注册发到无人监听的地址,服务悄悄消失- 多个实例(RAC、同机多实例)互相抢 1521 时,漏配 local_listener 会注册不齐
静态注册的坑:
- ORACLE_HOME 路径写错、SID 大小写不一致,
lsnrctl start直接起不来——改配置必须 reload 后验证 - UNKNOWN 状态不反映实例死活,依赖它判断"服务正常"会误判:库里挂着,监听侧看着一切正常
- 库换了版本、换了路径,listener.ora 忘了跟着改
七、生产建议
- 两者并存:默认 LISTENER 走动态(零维护、状态真实),同时配 SID_LIST_LISTENER 做静态兜底——这是省心的组合
- DG、需要远程恢复的库,静态注册列入强制装机项
- 变更检查清单加入两条:
lsnrctl services输出留档比对;listener.ora 和 ORACLE_HOME 的实际路径核对 - 监控里同时盯两样:动态条目消失(说明实例注册有问题)和 UNKNOWN 条目消失(说明 listener.ora 被动过)
- 应用连接串统一走 SERVICE_NAME;静态注册的 GLOBAL_DBNAME 命名与动态服务名保持一套规范,避免排查时对不上号
✅ 亮点:用"监听器里两本账"统一解释 READY/UNKNOWN、12514/01034 的现象差异,明确"库没起来要连、DG、远程恢复"三个必须静态注册的场景,最后给出"动态为主、静态兜底"的组合建议。扩展方向:RAC 中 SCAN 监听的 service 管理(srvctl add service)、基于 ONS/FAN 的快速故障通知。