Oracle RAC集群环境下,多个业务系统往往共享同一套数据库,一旦某个业务发起大批量查询或遭遇失控的PL/SQL循环,CPU资源会被瞬间吃满,连带影响其他关键业务。Database Resource Manager(简称DBRM)正是为解决这类问题而生的内置组件,它通过消费者组、资源计划和资源计划指令三层结构,将数据库会话按业务重要性分组,再为不同组分配CPU份额、并发上限和执行时间约束,从数据库内核层面实现资源隔离,不依赖操作系统级的资源控制。

一、Database Resource Manager的核心组件与工作原理
DBRM的体系结构由三个核心对象组成。第一个是消费者组(Consumer Group),它是一组具有相同资源需求的会话集合,比如可以把订单交易会话归入OLTP_GROUP,把报表查询会话归入REPORT_GROUP。第二个是资源计划(Resource Plan),它定义了资源在各个消费者组之间的分配策略。第三个是资源计划指令(Resource Plan Directive),它是计划中的具体规则条目,指定某个消费者组能获得多少CPU百分比、最多允许多少并行执行进程、单个会话执行多久会被终止等。
理解DBRM的调度机制很重要。DBRM在CPU调度上采用多层分配模型:资源计划第一层的消费者组按指定百分比瓜分CPU,如果某个组没有用完自己的份额,剩余CPU会流向第二层或其他未达上限的组,这比操作系统简单的nice值调度精细得多。需要强调的是,CPU分配发生在实例级别,也就是说在RAC的每一个实例内部,DBRM独立执行各自的调度,这一点在后面配置参数时会再次提到。
DBRM还提供四种资源控制能力:CPU方法与份额限制、并行执行服务器数量限制(PARALLEL_DEGREE_LIMIT_P1)、活跃会话池控制(ACTIVE_SESS_POOL_P1)以及会话切换规则(SWITCH_GROUP/SWITCH_TIME)。其中活跃会话池是防止低优先级业务占满资源的利器,超出池上限的会话会排队等待,而不是直接报错。
二、在RAC环境中创建消费者组与资源计划
创建DBRM配置需要DBA角色,并且必须在DRM激活状态下操作。下面的示例演示了完整的创建流程:先挂起当前计划,创建两个消费者组,再创建资源计划并添加指令,最后激活计划。
-- 以DBA身份执行,先挂起资源管理器
EXEC DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
-- 创建消费者组
EXEC DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP( -
CONSUMER_GROUP => 'OLTP_GROUP', -
COMMENT => '核心交易业务');
EXEC DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP( -
CONSUMER_GROUP => 'REPORT_GROUP', -
COMMENT => '报表与批量查询业务');
-- 创建资源计划
EXEC DBMS_RESOURCE_MANAGER.CREATE_PLAN( -
PLAN => 'RAC_DAY_PLAN', -
COMMENT => '白天业务时段资源计划');
-- 为计划添加指令:OLTP占70%CPU,报表占30%
EXEC DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE( -
PLAN => 'RAC_DAY_PLAN', -
GROUP_OR_SUBPLAN => 'OLTP_GROUP', -
MGMT_P1 => 70, -
PARALLEL_DEGREE_LIMIT_P1 => 4, -
ACTIVE_SESS_POOL_P1 => 20, -
SWITCH_GROUP => 'KILL_SESSION', -
SWITCH_TIME => 1800, -
SWITCH_ESTIMATE => TRUE);
EXEC DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE( -
PLAN => 'RAC_DAY_PLAN', -
GROUP_OR_SUBPLAN => 'REPORT_GROUP', -
MGMT_P1 => 30, -
PARALLEL_DEGREE_LIMIT_P1 => 16, -
ACTIVE_SESS_POOL_P1 => 5);
-- OTHER_GROUPS兜底指令,未分组会话默认进入
EXEC DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE( -
PLAN => 'RAC_DAY_PLAN', -
GROUP_OR_SUBPLAN => 'OTHER_GROUPS', -
MGMT_P1 => 0, -
MGMT_P2 => 100);
-- 校验并提交
EXEC DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();
EXEC DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
-- 激活资源计划
ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'RAC_DAY_PLAN' SCOPE=BOTH;
上面指令中的参数含义值得逐一说明。MGMT_P1表示第一层CPU分配的百分比,两个组的数值之和可以小于100,剩余部分会自动进入第二层MGMT_P2。报表组的ACTIVE_SESS_POOL_P1设为5,意味着该组同时最多5个活跃会话在执行,后续会话排队,这能有效防止报表任务把CPU打满。OLTP组的SWITCH_TIME配合SWITCH_ESTIMATE为TRUE,优化器会在执行前预估SQL耗时,超过1800秒的直接终止,避免长SQL长期霸占资源。
三、会话映射与RAC多实例环境下的注意事项
计划建好后还需要把会话映射到消费者组,常用做法是按登录属性映射,通过DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING设置。例如按数据库服务名区分,交易服务连进来的会话归入OLTP_GROUP,报表服务归入REPORT_GROUP。
-- 按服务名映射:交易服务 -> OLTP_GROUP
EXEC DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( -
ATTRIBUTE => DBMS_RESOURCE_MANAGER.ORACLE_USER, -
VALUE => 'APP_OLTP', -
CONSUMER_GROUP => 'OLTP_GROUP');
-- 按客户端机器名映射报表会话
EXEC DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( -
ATTRIBUTE => DBMS_RESOURCE_MANAGER.CLIENT_MACHINE, -
VALUE => 'report-server', -
CONSUMER_GROUP => 'REPORT_GROUP');
-- 为用户授予切换组的权限
EXEC DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SWITCH_CONSUMER_GROUP( -
GRANTEE_NAME => 'APP_OLTP', -
CONSUMER_GROUP => 'OLTP_GROUP', -
GRANT_OPTION => FALSE);
-- 查看当前会话所属的消费者组
SELECT sid, username, resource_consumer_group
FROM v$session
WHERE username IS NOT NULL;
RAC环境有几个特别需要注意的地方。首先是RESOURCE_MANAGER_PLAN参数的设置方式:如果希望两个实例使用不同计划,比如实例1跑交易、实例2专跑报表,可以在每个实例上用SID限定分别设置;如果想所有实例统一,则不指定SID即可,示例如下。
-- 实例1单独设置(交易实例) ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'RAC_DAY_PLAN' SCOPE=BOTH SID='RACDB1'; -- 实例2单独设置(报表实例) ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'RAC_NIGHT_PLAN' SCOPE=BOTH SID='RACDB2'; -- 不指定SID则对所有实例生效 ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'FORCE:' || 'RAC_DAY_PLAN' SCOPE=BOTH;
其次要注意,计划名称前加FORCE:前缀会禁用Oracle自动维护任务对该计划的临时切换,这在排障时很有用,可以确保观测到的是你自己定义的计划行为。另外RAC中推荐结合服务(Service)做负载分离,把不同业务的连接通过服务路由到不同实例,再配合实例级计划,能达到接近物理隔离的效果。
四、监控与常见问题排查
配置完成后,监控是保证DBRM持续有效的关键环节。几个常用视图值得掌握:V$RSRC_PLAN显示当前实例激活的计划,V$RSRC_CONSUMER_GROUP展示每个消费者组的CPU消耗、排队会话数和被切换次数,DBA_RSRC_CONSUMER_GROUP_PRIVS则记录了组与用户的授权关系。
-- 查看当前实例激活的资源计划
SELECT name, is_top_plan
FROM v$rsrc_plan;
-- 查看各消费者组资源消耗情况
SELECT con_id, name, active_sessions, queued_sessions,
cpu_consumed_time/100000 AS cpu_seconds,
requests, active_sess_pool_wait_time
FROM v$rsrc_consumer_group
ORDER BY cpu_consumed_time DESC;
-- 查看被排队或被切换的会话原因
SELECT sid, event, seq#, wait_time
FROM v$session
WHERE event LIKE 'resmgr:%';
排查问题时常见两类现象。一是会话等待事件显示为resmgr:active session pool wait,说明该组活跃会话池已满,会话在排队,这时要评估是调大池值还是限制业务并发;二是会话被自动切换到OTHER_GROUPS或被KILL,通常是映射规则没匹配上或者执行时间超限,需要检查DBA_RSRC_GROUP_MAPPINGS中的映射优先级。另外提醒一点,修改资源计划必须经过PENDING_AREA的创建、提交流程,直接调用CREATE过程而不挂起区域会报ORA-29370错误,这是新手最容易踩的坑。
总结来看,在RAC集群中落地DBRM,思路可以归纳为:按业务划分消费者组,按优先级分配CPU份额,用活跃会话池和并行度限制兜底,用执行时间切换规则拦截失控SQL,最后借助实例级参数与服务分离实现多实例的差异化策略。这套机制配合AWR报告中的Resource Manager统计段,能让数据库资源分配真正变得透明可控。
Oracle RACDatabase Resource Manager资源管理修改时间:2026-09-07 11:30:59