service_name重启后消失的根源是PL/SQL创建的服务未持久化至OCR,RAC环境下必须用srvctl add service注册;修复方式为:单机执行alter pluggable database pdb_name save state,RAC必须用srvctl add service -preferred/-available正确配置并验证srvctl status service。
service_name重启后消失的根源和修复方式
这是多租户 + rac 环境下最常踩的坑:用 dbms_service.create_service 创建的服务,cdb 重启后就没了。根本原因在于服务状态没持久化——pl/sql 方式创建的服务默认只存在于内存中,不写入 ocr 或控制文件。
单机环境补救办法是执行 alter pluggable database <pdb_name> save state</pdb_name>;RAC 环境必须用 srvctl 注册到 OCR,否则无论怎么 start_service 都只是临时生效。
- 单机测试可接受临时服务:创建后立即调用
dbms_service.start_service,再执行alter pluggable database <pdb_name> save state</pdb_name> - RAC 生产环境严禁用 PL/SQL 创建服务:必须用
srvctl addservice,且-preferred和-available实例列表要与实际节点数匹配 - 验证是否持久:重启任意节点后,运行
srvctl status service -d <cdb_name> -s <service_name></service_name></cdb_name>,输出 “is running” 才算真正落地
srvctl addservice 的 -preferred 和 -available 参数误用后果
这两个参数直接决定客户端连接路由行为。填错会导致负载不均、故障转移失败,甚至部分实例完全收不到连接请求。
典型错误是把所有实例都写进 -preferred,结果客户端永远只连第一个;或者漏写 -available,当 preferred 实例宕机时服务直接不可用。
-
-preferred列表里的实例会优先接收新连接,顺序有影响(Oracle 按列表顺序轮询) -
-available是故障转移兜底池,必须包含至少一个不在-preferred中的实例 - RAC 双节点建议配置:
-preferred cdb1 -available cdb2,避免两个都 preferred 导致粘滞 - 修改后必须执行
srvctl stopservice+srvctl startservice才生效,modifyservice不触发重载
dbms_service.start_service 在 RAC 中的实例范围陷阱
在 PDB 内执行 dbms_service.start_service 时,如果不指定实例范围,默认只启动当前连接所在实例上的服务副本。这在 RAC 下等于只启了一半,其他节点无法响应该 service 的连接请求。
必须显式传入 DBMS_SERVICE.ALL_INSTANCES,否则会出现“服务看起来在运行,但客户端连不上”的诡异现象。
- 正确调用:
exec dbms_service.start_service('myapp.pdb', DBMS_SERVICE.ALL_INSTANCES) - 错误调用:
exec dbms_service.start_service('myapp.pdb')—— 仅当前实例生效 - 该函数无返回值,执行后需查
v$active_services确认各实例状态,字段inst_id要覆盖全部节点
PDB 级 service 与 CDB 级 service 的混用风险
一个 service 绑定到 PDB 后,其连接字符串中的 SERVICE_NAME 必须精确匹配 PDB 的 network_name(查 cdb_services.network_name),不能混用 CDB 根的服务名。
常见错误是开发用 CDB 的 service 连 PDB,或在 tnsnames.ora 里把 PDB service 名写成 CDB 名,结果报错 ORA-12514: TNS:listener does not currently know of service requested in connect descriptor。
- 确认 PDB service 是否启用:
select name, network_name from cdb_services where pdb = '<pdb_name>'</pdb_name> - TNS 配置中
SERVICE_NAME值必须与查询结果的network_name完全一致(区分大小写) - CDB 根的服务(如
cmancdb)只能访问 CDB$ROOT,不能跨容器访问 PDB 对象
GLOBAL_DBNAME 映射,客户端照样连不上。这个步骤必须手动补上。











