Oracle数据库在运行过程中,经常遇到这样的情况:一张报表SQL消耗了大部分CPU,导致在线交易系统响应缓慢;或者某个开发人员在生产库上跑大批量更新,把活跃会话数和并行资源全部占满。单纯靠用户自觉或者杀会话治标不治本,Oracle Resource Manager(资源管理器)正是为解决这类问题而生的内建工具。它允许DBA把数据库资源按照预先定义的规则分配给不同的使用者,做到核心业务优先、次要任务限量,从数据库内核层面实现资源的隔离与调度。

一、先搞懂Resource Manager的四个核心概念
配置资源管理器之前,必须理解它的架构模型,否则后面写的计划指令会一头雾水。Resource Manager由四个核心对象组成:待处理区域(Pending Area)、消费组(Consumer Group)、资源计划(Resource Plan)和计划指令(Plan Directive)。它们的关系可以类比为:资源计划是一份总方案,消费组是资源分配的单位,计划指令定义了每个消费组能拿到多少资源,而待处理区域则是所有配置工作的草稿区。
待处理区域是理解配置流程的关键。所有的创建和修改操作都必须先在待处理区域中进行,相当于一个暂存的工作区。在待处理区域里完成所有变更后,通过提交流程一次性生效,这样可以保证配置的原子性和一致性,不会出现配置到一半数据库就带着残缺规则运行的情况。
消费组则是对用户或会话的分类。比如可以把ERP系统的会话归入OLTP_GROUP,把报表类会话归入REPORT_GROUP,把维护作业归入MAINT_GROUP。同一个用户在不同时刻可以被映射到不同的消费组,这取决于映射规则的优先级设置。数据库默认自带SYS_GROUP和其他系统消费组,自带计划中通常已经做了一些基础分配,我们完全可以基于默认计划改造,也可以从零建立自己的计划。
二、创建消费组和资源计划的完整步骤
所有配置都通过DBMS_RESOURCE_MANAGER包完成,以下操作需要具有ADMINISTER RESOURCE MANAGER权限的用户执行,通常用SYS登录。第一步永远是创建待处理区域,如果忘记这一步,后续任何创建过程都会报ORA-29371错误。
-- 第一步:创建待处理区域
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
END;
/
-- 第二步:创建消费组
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP(
CONSUMER_GROUP => 'OLTP_GROUP',
COMMENT => '在线交易业务组');
DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP(
CONSUMER_GROUP => 'REPORT_GROUP',
COMMENT => '报表统计业务组');
END;
/
-- 第三步:创建资源计划
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_PLAN(
PLAN => 'DAYTIME_PLAN',
COMMENT => '白天业务时段资源计划');
END;
/
-- 第四步:创建计划指令,分配CPU比例
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
PLAN => 'DAYTIME_PLAN',
GROUP_OR_SUBPLAN => 'OLTP_GROUP',
MGMT_P1 => 70, -- 第一级CPU分配70%
MGMT_P2 => 0,
PARALLEL_DEGREE_LIMIT_P1 => 4,
SESSION_P1 => 50);
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
PLAN => 'DAYTIME_PLAN',
GROUP_OR_SUBPLAN => 'REPORT_GROUP',
MGMT_P1 => 25, -- 第一级CPU分配25%
MGMT_P2 => 0,
PARALLEL_DEGREE_LIMIT_P1 => 8,
SESSION_P1 => 20);
-- OTHER_GROUPS必须包含,兜底接收未匹配的会话
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
PLAN => 'DAYTIME_PLAN',
GROUP_OR_SUBPLAN => 'OTHER_GROUPS',
MGMT_P1 => 5,
MGMT_P2 => 0);
END;
/
-- 第五步:校验并提交待处理区域
BEGIN
DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();
DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
END;
/需要特别注意的是OTHER_GROUPS这个指令。任何资源计划都必须为OTHER_GROUPS定义指令,否则提交时会校验失败。所有没有被明确映射到消费组的会话都会落入OTHER_GROUPS,如果忘记给它分配资源,这些会话将无法获得CPU,业务会直接卡死。
关于CPU分配的层级,MGMT_P1到MGMT_P4代表四个分配级别。资源管理器优先满足第一级的需求,第一级用不完的剩余资源才向下一级分配。上面的例子中,OLTP组在70%的CPU额度内可以完全保证性能,而REPORT组即使满负荷也最多拿25%,剩下的5%留给未分类会话。当某个组实际用不到自己的配额时,空闲资源会被其他组共享,所以不会造成浪费。
三、把会话映射到消费组并启用计划
计划建好后只是定义了规则,还需要告诉数据库哪些会话属于哪个消费组。映射方式有三种:按数据库用户名、按操作系统用户名、按客户端机器名或服务名,也可以通过登录触发器手动切换。最常用的是按用户名映射,配合优先级参数使用。
-- 将用户ERP_USER映射到OLTP_GROUP,优先级最高(数字越小优先级越高)
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
PLAN => 'DAYTIME_PLAN',
GROUP_OR_SUBPLAN => 'OLTP_GROUP',
COMMENT => 'placeholder');
END;
/
BEGIN
DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SWITCH_CONSUMER_GROUP(
GRANTEE_NAME => 'ERP_USER',
CONSUMER_GROUP => 'OLTP_GROUP',
GRANT_OPTION => FALSE);
END;
/
BEGIN
DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING(
ATTRIBUTE => DBMS_RESOURCE_MANAGER.ORACLE_USER,
VALUE => 'ERP_USER',
CONSUMER_GROUP => 'OLTP_GROUP');
END;
/
-- 启用资源计划
ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'DAYTIME_PLAN' SCOPE = BOTH;启用计划的另一种方式是把RESOURCE_MANAGER_PLAN参数写进spfile,这样数据库重启后计划依然生效。如果要实现白天和夜间自动切换不同的计划,可以使用调度器窗口(Scheduler Window)绑定不同计划,数据库会按时间窗口自动切换,无需人工干预。
验证配置是否生效,可以查询相关数据字典视图。常用的有DBA_RSRC_PLANS查看所有计划、DBA_RSRC_CONSUMER_GROUPS查看消费组、DBA_RSRC_PLAN_DIRECTIVES查看计划指令明细,以及V$RSRC_CONSUMER_GROUP查看每个组实时的CPU消耗情况。比如在Windows环境下,用SQL*Plus连接后执行以下查询:
-- 查看当前生效的资源计划
SELECT name, cpu_managed FROM V$RSRC_PLAN;
-- 查看各消费组实时CPU使用情况
SELECT name, active_sessions, cpu_consumed_time,
requests, current_queued
FROM V$RSRC_CONSUMER_GROUP;
-- 查看某个会话当前所属的消费组
SELECT sid, username, resource_consumer_group
FROM V$SESSION
WHERE username IS NOT NULL;如果要临时禁用资源管理器,把参数设为空即可:ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = '',所有会话回归公平调度。需要注意,禁用后原有的映射规则仍然保留在数据字典中,下次启用同一计划时无需重新配置,这也是资源管理器相对脚本轮询杀会话方案的一大优势:配置一次,长期有效。
四、进阶:执行时间限制与切换组自动降级
除了CPU配额,资源管理器还支持对单条SQL的执行时间设限。通过计划指令中的MAX_EST_EXEC_TIME参数,优化器在硬解析阶段估算执行时间,一旦超过阈值就直接报ORA-07455错误拒绝执行,避免一条失控SQL拖垮整个库。相对温和的做法是用SWITCH_GROUP参数,当SQL执行超过SWITCH_TIME设定的秒数时,会话被自动切换到指定的低优先级组继续执行,而不是直接杀掉,适合报表类任务错峰降级的场景。
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
PLAN => 'DAYTIME_PLAN',
GROUP_OR_SUBPLAN => 'REPORT_GROUP',
MGMT_P1 => 25,
MAX_EST_EXEC_TIME => 1800, -- 估算执行超过1800秒直接拒绝
SWITCH_GROUP => 'LOW_GROUP', -- 实际执行超时切换到低优先级组
SWITCH_TIME => 600, -- 运行超过600秒触发切换
SWITCH_FOR_CALL => TRUE); -- 调用结束后切回原组
DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
END;
/SWITCH_FOR_CALL设为TRUE表示只对当前这条SQL生效,执行完毕后会话自动回到原消费组,下次新SQL重新按原规则评估,这种方式对批处理作业非常友好。整体来看,Resource Manager的配置过程虽然步骤较多,但逻辑清晰:建待处理区域、建消费组、建计划、写指令、提交、映射、启用,七步走完就拥有了一套内核级的资源隔离体系,比任何外部监控脚本都更及时、更可靠。
Oracle Resource Manager资源计划数据库资源管理修改时间:2026-09-14 22:13:26