rac中pdb服务必须用srvctl显式添加并绑定resource manager才能实现路由与资源双重隔离,因默认注册不跨节点、无负载策略且不保存状态。

为什么RAC里PDB服务不能只靠默认注册
在RAC环境中,PDB创建后执行 ALTER SYSTEM REGISTER; 只会让当前节点的监听器动态注册该PDB的服务名,另一个节点不会同步。这意味着客户端如果连接到未注册服务的节点,就会报 ORA-12514: TNS:listener does not currently know of service requested in connect descriptor。这不是配置遗漏,而是Oracle监听器的本地性设计决定的——每个节点监听器独立维护服务注册表。
更麻烦的是,即使两个节点都注册了同一PDB的服务名(比如 PDB01),默认情况下这个服务会跨所有实例运行,无法实现按业务或租户做负载隔离。
- 默认注册不跨节点:必须在每个RAC节点上分别执行
ALTER SYSTEM REGISTER;或重启监听器 - 动态注册的服务没有负载策略:它会在所有在线实例间轮询分发连接,无法绑定特定实例
- 服务名冲突风险高:多个PDB若用相同服务名(如都叫
PDB1),会导致路由混乱 - RAC中
SAVE STATE不生效:PDB状态不会在集群重启后自动恢复,服务注册也一样
srvctl add service 是唯一可控的生产级方案
Oracle官方推荐且唯一能精确控制PDB服务生命周期、实例亲和性与故障转移行为的方式,是用 srvctl 命令显式添加服务。它写入OCR(Oracle Cluster Registry),由CRS统一管理,支持节点亲和、启动顺序、故障转移策略等关键能力。
例如,为PDB SalesPDB 配置仅在节点1运行、故障时不转移的服务:
srvctl add service -db ORCLCDB -service "salespdb_rac1" -preferred "orcl1" -available "" -failover_type NONE -failover_method NONE -failover_retries 0 -failover_delay 0
然后启动服务:
srvctl start service -db ORCLCDB -service "salespdb_rac1"
- 必须用
-db指定CDB的DB Unique Name(不是SID),可通过srvctl config database查看 -
-preferred和-available控制实例亲和:留空-available表示不启用故障转移 - 服务名必须全局唯一,建议带环境/角色后缀(如
salespdb_prod、salespdb_report) - 添加后需在PDB内手动创建同名服务:在
SalesPDB中执行exec dbms_service.create_service('salespdb_rac1', 'salespdb_rac1');,再exec dbms_service.start_service('salespdb_rac1');
TNS连接串必须匹配srvctl定义的服务名
应用不能继续用PDB名称当服务名(如 @host:1521/SalesPDB),而必须使用 srvctl 创建的服务名(如 @host:1521/salespdb_rac1)。否则监听器虽看到请求,但找不到对应服务句柄,仍报 ORA-12514。
典型TNS配置($ORACLE_HOME/network/admin/tnsnames.ora):
SALPDB_RAC1 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = p19c-scan)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = salespdb_rac1)
)
)
- SCAN地址必须指向RAC集群SCAN VIP,不能写单节点IP,否则失去负载均衡能力
- 不要在
CONNECT_DATA中加SID—— RAC+PDB下SID无意义,只认SERVICE_NAME - JDBC连接需显式指定
oracle.net.tns_admin指向正确tnsnames.ora目录,或直接用EZConnect格式:jdbc:oracle:thin:@//p19c-scan:1521/salespdb_rac1
资源隔离要靠服务+Resource Manager双控
光有服务名隔离还不够。RAC节点上的多个PDB服务可能共享同一组CPU和I/O资源。必须配合CDB级Resource Manager Plan,把服务名映射到资源组,才能真正实现负载隔离。
例如,在CDB$ROOT中创建plan并绑定:
CREATE PLAN pdb_sales_plan; ADD DIRECTIVE plan => 'pdb_sales_plan', group_or_subplan => 'SALES_GROUP', comment => 'For SalesPDB workloads', service => 'salespdb_rac1', mgmt_p1 => 60; ALTER SYSTEM SET resource_manager_plan = 'pdb_sales_plan';
- 每个服务名只能绑定一个资源组;多个服务可共用同一组,但无法反向映射
-
mgmt_p1值越大,优先级越高;RAC中该设置对所有节点生效 - 验证是否生效:查
v$rsrc_consumer_group和v$session的resource_consumer_group字段 - 别漏掉PDB内用户授权:在
SalesPDB中执行ALTER USER sales_app SET DEFAULT ROLE ALL;确保其会话被正确归类
最易被忽略的是服务名与Resource Manager的绑定关系——它不随PDB自动继承,也不在 srvctl 命令中体现,必须人工在CDB$ROOT中显式创建并启用。少这一步,前面所有服务配置都只是“路由隔离”,而非“资源隔离”。











