必须先在CDB$ROOT启用RESOURCE_MANAGER_PLAN(如DEFAULT_PLAN),否则cpu_count、cpu_min_count、pdb_memory_limit等PDB级资源参数均不生效;再于目标PDB中设置具体值,并配合profile控制并发、注意IO限值适用范围。
怎么确认当前PDB有没有启用资源管理
没开 resource_manager_plan,所有 cpu_count、cpu_min_count、pdb_memory_limit 都不生效——这是最常被忽略的前提。cdb 默认不启用资源计划,哪怕你改了参数,也等于没设。
- 查 CDB 当前是否启用:
SELECT plan, status FROM DBA_RSRC_PLANS WHERE status = 'ACTIVE';,再看SELECT value FROM v$parameter WHERE name = 'resource_manager_plan';是否非空 - 必须在 CDB$ROOT 执行:
ALTER SYSTEM SET resource_manager_plan = 'DEFAULT_PLAN' SCOPE=BOTH;(DEFAULT_PLAN是 Oracle 自带的、支持 PDB 级别控制的基础计划) - 注意:不是所有 plan 都支持 PDB 级资源指令;自定义 plan 若没显式包含
PDB_DIRECTIVE,改 PDB 参数也没用
怎么给单个PDB设CPU硬限制(不是配额,是上限)
cpu_count 是 PDB 能用的最大并发线程数(逻辑 CPU),不是物理核数,也不是百分比——它直接卡死并行度和前台进程调度上限。设成 2,意味着哪怕 CDB 有 48 核,这个 PDB 永远拿不到第 3 个线程。
- 进目标 PDB:
ALTER SESSION SET CONTAINER = pdb01; - 设最大可用线程数:
ALTER SYSTEM SET cpu_count = 2 SCOPE=BOTH; - 设保底线程数(防饥饿):
ALTER SYSTEM SET cpu_min_count = 1 SCOPE=BOTH;(小数如0.5仅在cpu_count为整数时按比例算,不推荐混用) - 坑:如果
cpu_min_count > cpu_count,启动会报错 ORA-600;如果只设cpu_count不设cpu_min_count,保底为 0,高负载时可能被彻底饿死
怎么限制PDB内存用量(SGA+PGA总和)
Oracle 19c 引入 pdb_memory_limit,这才是真正意义上的 PDB 内存硬限。它管的是该 PDB 所有进程 SGA+PGA 的总和,单位是字节(但支持 1G、2048M 这类写法),超限后新连接或大排序操作会直接报 ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT 或触发自动终止会话。
- 在 CDB$ROOT 中对指定 PDB 设限:
ALTER PLUGGABLE DATABASE pdb01 SET PARAMETER pdb_memory_limit = '4G'; - 立即生效(无需重启 PDB),但只影响后续新建会话;已有会话继续运行,直到其 PGA/SGA 增长触碰全局
pga_aggregate_limit或sga_target - 坑:
pdb_memory_limit不拆分 SGA/PGA,也不替代sga_target或pga_aggregate_target;若后者设得过大(比如pga_aggregate_target=2G),而pdb_memory_limit=1G,则 PDB 可能因 PGA 分配失败而报错,需协同调低 - 验证是否生效:
SELECT con_id, name, value FROM v$system_parameter2 WHERE name = 'pdb_memory_limit' AND con_id = (SELECT con_id FROM cdb_pdbs WHERE pdb_name = 'PDB01');
为什么IO和并发限制不能只靠参数硬控
max_iops 和 max_mbps 看似能限 IO,但它们只约束用户 I/O(如全表扫描、索引范围扫描),不拦 LGWR、DBWR、归档等后台关键 IO;而并发控制(比如会话数)根本不在资源计划里管——它得靠 profile。
- IO 限值检查:
SELECT con_id, pdb_name, iops, iombps FROM v$rsrcpdbmetric NATURAL JOIN cdb_pdbs ORDER BY iops DESC;,注意iops_throttle_exempt字段会显示被豁免的 IO 次数,高了说明限流实际效果打折 - 并发要靠 profile:
CREATE PROFILE pdb01_prof LIMIT sessions_per_user 50;,再ALTER USER app_user PROFILE pdb01_prof;;注意 profile 对 sysdba 用户无效,且不防应用层连接池滥用 - 坑:
max_iops=0表示不限,但很多 DBA 误以为“没设就是不限”,其实 CDB$ROOT 的 0 会被继承,必须显式在 PDB 里设非零值才生效;另外,这些 IO 参数在 RAC 中每个实例独立计数,不是全局统一限流
真正起作用的永远是「CDB 开了 plan + PDB 设了参数 + 应用行为匹配预期」这三者同时成立。漏掉任何一环,比如忘了在 CDB$ROOT 启用 DEFAULT_PLAN,或者 profile 没绑到真实业务用户,限制就只是躺在数据字典里的几行记录。










