
好的,我们将对 Oracle 数据库资源管理器(Database Resource Manager, DRM)进行一场极其深入和全面的剖析。这是一个用于在数据库内部管理和分配系统资源(主要是 CPU 和并行度)的高级功能,对于实现多租户环境下的服务质量(QoS)和混合工作负载管理至关重要。
第一部分:官方技术详解
一、核心概念与作用
1. 什么是资源管理器?
Oracle 资源管理器允许你在数据库内部,对并发会话和语句所使用的系统资源进行精细化的控制和分配。它解决了操作系统资源管理(如 CPU 优先级)无法感知数据库工作负载类型的问题,实现了数据库感知的(Database-Aware)资源分配。
2. 核心作用
- 资源隔离(Isolation):防止“喧闹的邻居”(如一个大型报表查询)耗尽所有资源,导致关键业务(如 OLTP 交易)性能受损。
- 资源分配(Allocation):根据业务优先级,为不同的用户、应用程序或工作负载类型保证特定比例的 CPU 资源。
- 执行控制(Execution Control):限制会话的空闲时间、执行时间,或自动切换长时间运行会话的消费者组。
- 并行度管理(Parallelism Management):限制特定操作(如查询)可以使用的并行服务器进程数量。
- 实例缓存(In-Memory Column Store)管理:在 Oracle 12c+ 中,还可以管理 IM 列存储的分配。
二、内部架构与核心组件
DRM 通过一个由元数据定义的规则系统来工作,其主要组件如下:
1. 资源消费者组 (Resource Consumer Group)
- 本质:一组具有相似资源需求的会话的逻辑集合。它是资源分配的目标对象。
- 类型:
- 默认组:
DEFAULT_CONSUMER_GROUP(默认)、BATCH_GROUP、INTERACTIVE_GROUP等。 - 用户自定义组:如
OLTP_GROUP,REPORTING_GROUP,ETL_GROUP。
- 默认组:
- 机制:一个会话在任何时刻都属于一个且仅属于一个消费者组。会话可以在不同组间动态切换。
2. 资源计划 (Resource Plan)
- 本质:资源分配的“预算方案”。它定义了资源如何在不同消费者组之间进行分配。
- 核心指令(Directive):计划的核心是资源计划指令(Resource Plan Directive),它指明了:
- 将多少资源(CPU)分配给哪个消费者组。
- 在哪个级别(Level)进行分配。
- 其他限制,如并行度、队列超时等。
- 多级分配(Multi-Level Scheduling):这是理解 CPU 分配的关键。一个计划可以包含多个级别(通常为 1-8)。Level 1 优先于 Level 2。只有在 Level 1 的所有分配需求得到满足后,剩余的 CPU 资源才会按照 Level 2 的规则进行分配,依此类推。
3. 资源计划指令 (Resource Plan Directive)
这是连接资源计划和资源消费者组的桥梁。它包含了具体的分配规则。一条指令的关键属性包括:
GROUP_OR_SUBPLAN:指令所针对的消费者组或子计划。MGMT_Pn:在级别n上,保证分配给该组的 CPU 资源百分比。PARALLEL_DEGREE_LIMIT_P1:限制该组中操作的最大并行度。ACTIVE_SESS_POOL_P1:限制该组中同时处于活动状态的会话数。QUEUEING_P1:指定会话在等待执行前可以在队列中等待的时间。UNDO_POOL:限制该组可以生成的总 UNDO 数据量。
4. 子计划 (Subplan)
一个资源计划可以包含另一个资源计划,称为子计划。这允许你创建层次化的资源分配结构,实现更复杂的管理策略。
三、CPU 分配与插值法(Interpolation)原理
这是 DRM 最核心、最精妙的部分。它决定了当资源未完全利用时,如何重新分配“剩余”资源。
1. 基于级别的按比例分配
假设我们有一个如下简单的计划,在 LEVEL 1 分配 100% CPU:
MGMT_P1 = 80%给OLTP_GROUPMGMT_P1 = 20%给REPORTING_GROUP
在这种情况下,OLTP_GROUP 将获得至少 80% 的 CPU,REPORTING_GROUP 获得至少 20%。如果 OLTP_GROUP 只用掉了 50%,那多余的 30% 并不会自动给 REPORTING_GROUP。REPORTING_GROUP 仍然被限制在 20%。这会导致资源浪费。
2. 多级分配与插值法(重点)
为了解决上述浪费问题,引入了多级分配。插值法的核心思想是:将更高优先级(更低Level)未使用的资源,按比例重新分配给较低优先级(更高Level)的消费者组。
举例说明:
创建一个包含两个级别的计划 NIGHT_PLAN:
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_PLAN(plan => 'NIGHT_PLAN', comment => 'Plan for night batch processing');
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
plan => 'NIGHT_PLAN',
group_or_subplan => 'CRITICAL_BATCH_GROUP',
mgmt_p1 => 70, -- Level 1: 保证70%
mgmt_p2 => 0 -- Level 2: 不参与分配
);
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
plan => 'NIGHT_PLAN',
group_or_subplan => 'LOW_PRIORITY_BATCH_GROUP',
mgmt_p1 => 0, -- Level 1: 不保证
mgmt_p2 => 100 -- Level 2: 参与分配剩余资源
);
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
plan => 'NIGHT_PLAN',
group_or_subplan => 'OTHER_GROUPS',
mgmt_p1 => 30, -- Level 1: 保证30%
mgmt_p2 => 0
);
END;
/
- 分配逻辑:
- Level 1 分配:首先,
CRITICAL_BATCH_GROUP被保证获得 70% 的 CPU,OTHER_GROUPS被保证获得 30%。LOW_PRIORITY_BATCH_GROUP在 Level 1 的分配为 0。 - 资源利用情况:
- 场景 A:如果
CRITICAL_BATCH_GROUP使用了全部的 70%,OTHER_GROUPS只使用了 10%。 - 那么,Level 1 总共使用了
70% + 10% = 80%。 - 剩余 20% 的 CPU 资源将进入 Level 2 进行分配。
- 场景 A:如果
- Level 2 分配(插值法发生于此):
- 在 Level 2,只有
LOW_PRIORITY_BATCH_GROUP一个组有分配指令(MGMT_P2 = 100)。 - 因此,这 20% 的剩余资源将全部分配给
LOW_PRIORITY_BATCH_GROUP。 - 最终实际分配:
CRITICAL_BATCH_GROUP: 70%OTHER_GROUPS: 10%LOW_PRIORITY_BATCH_GROUP: 20%
- 在 Level 2,只有
- Level 1 分配:首先,
这个例子展示了插值法如何将高优先级未使用的资源“滑落”到低优先级。如果有多个组在 Level 2 参与分配,则剩余资源会按它们在 Level 2 的 MGMT_Pn 权重比例进行分配。
四、详细管理机制与配置流程
配置 DRM 是一个多步骤的过程,必须使用 DBMS_RESOURCE_MANAGER 包。
1. 创建未决区域(Pending Area)
所有创建和修改操作都必须在一个“沙箱”中进行。
BEGIN
DBMS_RESOURCE_MANAGER.CLEAR_PENDING_AREA();
DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
END;
/
2. 创建消费者组
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP(
consumer_group => 'OLTP_GROUP',
comment => 'Group for OLTP transactions'
);
DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP(
consumer_group => 'REPORTING_GROUP',
comment => 'Group for reporting queries'
);
END;
/
3. 创建资源计划与指令
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_PLAN(
plan => 'DAYTIME_PLAN',
comment => 'Plan for daytime workload'
);
-- 指令1: OLTP 组在 Level 1 获得 60%,并行度限制为 2
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
plan => 'DAYTIME_PLAN',
group_or_subplan => 'OLTP_GROUP',
mgmt_p1 => 60,
parallel_degree_limit_p1 => 2
);
-- 指令2: 报表组在 Level 1 获得 20%,在 Level 2 参与分配
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
plan => 'DAYTIME_PLAN',
group_or_subplan => 'REPORTING_GROUP',
mgmt_p1 => 20,
mgmt_p2 => 50 -- 在Level 2的权重是50%
);
-- 指令3: 必须包含 OTHER_GROUPS
DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
plan => 'DAYTIME_PLAN',
group_or_subplan => 'OTHER_GROUPS',
mgmt_p1 => 20,
mgmt_p2 => 50 -- 在Level 2的权重是50%
);
END;
/
4. 验证并提交未决区域
BEGIN
DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();
DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
END;
/
5. 分配用户/会话到消费者组
-- 将用户 SCOTT 的默认组设置为 REPORTING_GROUP
BEGIN
DBMS_RESOURCE_MANAGER.SET_INITIAL_CONSUMER_GROUP(
user => 'SCOTT',
consumer_group => 'REPORTING_GROUP'
);
END;
/
-- 手动切换当前会话的组
BEGIN
DBMS_SESSION.SWITCH_CURRENT_CONSUMER_GROUP(
new_consumer_group => 'OLTP_GROUP',
old_consumer_group => :old_group, -- 返回原来的组
initial_group_on_error => FALSE
);
END;
/
6. 激活资源计划
-- 在实例级别激活(需要重启或修改参数)
ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'DAYTIME_PLAN';
-- 或在会话级别激活(用于测试)
ALTER SESSION SET RESOURCE_MANAGER_PLAN = 'DAYTIME_PLAN';
第二部分:场景、争用、排查与解决
五、性能争用与排查
DRM 本身是为了减少争用而设计的,但配置不当或资源严重不足时,会引入新的等待事件。
1. 场景:资源争用与队列
- 原理:当某个消费者组的活跃会话数达到
ACTIVE_SESS_POOL_P1的限制,或 CPU 资源无法满足所有组的保证比例时,新的会话或请求需要排队等待。 - 等待事件:
resmgr: cpu quantum:这是最主要的 DRM 等待事件。它表示一个会话已经用完了它在当前调度周期内被分配到的 CPU 时间片,正在等待下一个时间片。这是正常的、预期的行为,表明 DRM 正在工作。但如果该事件的等待时间很长,则说明该消费者组竞争 CPU 非常激烈。resmgr: become active:会话在等待消费者组的“活跃会话池”中有空位。这表明ACTIVE_SESS_POOL_P1设置可能过小,或者有太多会话试图同时运行。
- 排查:
- 查询
V$SESSION查看会话正在等待什么事件。 - 使用
V$RSRC_CONSUMER_GROUP视图监控各个消费者组的资源使用情况和队列状态。SELECT name, active_sessions, -- 当前活跃会话数 execution_waiters, -- 等待被调度的会话数 cpu_wait_time, -- 在队列中的总等待时间 consumed_cpu_time -- 消耗的CPU时间 FROM v$rsrc_consumer_group; - 查看 AWR 报告的 “Resource Manager Stats” 部分,了解各组的 CPU 使用率、等待时间和队列长度。
- 查询
- 解决:
- 如果
resmgr: cpu quantum等待过高,可能需要调整资源计划,为该组分配更高的 CPU 比例,或者检查系统总体 CPU 资源是否充足。 - 如果
resmgr: become active等待过高,可以考虑适当增大ACTIVE_SESS_POOL_P1的值,或者优化应用程序减少并发请求。
- 如果
2. 场景:并行度限制
- 原理:如果
PARALLEL_DEGREE_LIMIT_P1设置过低,对于本可以从并行执行中获益的大型查询,其性能会下降。 - 影响:查询执行时间变长,但可能避免了系统级的 I/O 和 CPU 争用。
- 排查:检查执行计划,确认查询是否使用了低于预期的并行度。
- 解决:平衡系统整体吞吐量和单个查询性能,适当调整并行度限制。
六、常用查询与管理 SQL
-
查看当前激活的资源计划:
SELECT name, is_top_plan FROM v$rsrc_plan; -
监控消费者组状态(实时):
SELECT sid, serial#, username, resource_consumer_group, state FROM v$session WHERE resource_consumer_group IS NOT NULL; -
查看所有资源计划指令:
SELECT plan, group_or_subplan, mgmt_p1, mgmt_p2, mgmt_p3, mgmt_p4, parallel_degree_limit_p1, active_sess_pool_p1, queueing_p1 FROM dba_rsrc_plan_directives ORDER BY plan, mgmt_p1 DESC NULLS LAST; -
查看用户与消费者组的映射关系:
SELECT username, initial_rsrc_consumer_group FROM dba_users; -
生成 DRM 相关的 AWR 报告:在 AWR 报告中,“Resource Manager Stats” 部分提供了宝贵的历史信息。
第三部分:通俗易懂的解释
想象一下数据库是一个 CPU 蛋糕。资源管理器就是分蛋糕的规则。
- 消费者组:就是来分蛋糕的人。比如“销售部”、“市场部”、“财务部”。
- 资源计划:就是 CEO 批准的“分蛋糕规则书”。
- 资源计划指令:就是规则书里的具体条款:“销售部先分 60%,市场部分 20%,财务部分 20%”。
最简单的分法(单级分配):
CEO 规定:销售部切走 60%,市场部 20%,财务部 20%。就算销售部只吃了 40%,剩下的 20% 也不能给别人,只能扔掉(浪费了)。市场部和财务部再饿,也只能吃自己那 20%。
更聪明的分法(多级分配与插值法):
CEO 制定了更复杂的规则:
- 第一轮(Level 1):销售部必须先拿 60%,财务部必须先拿 20%。
- 第二轮(Level 2):如果第一轮有剩余,市场部可以参与瓜分剩余的部分。
- 某天,销售部很忙,吃光了 60%。财务部不饿,只吃了 10%。
- 剩下
100% - 60% - 10% = 30%的蛋糕。 - 这 30% 全部归市场部。
- 最终结果:销售部 60%,财务部 10%,市场部 30%。避免了浪费,提高了蛋糕利用率。
如果大家都没吃饱(争用):
如果蛋糕太小(CPU 资源不足),所有人都吃不饱。销售部的人(会话)虽然优先权高,但也要等厨师(CPU)一块一块地切给他们吃,这个过程就是 resmgr: cpu quantum 等待。市场部的人则排在更后面,他们不仅要等厨师,还要等销售部和财务部先拿完,他们的等待可能表现为 resmgr: become active。
DBA 的角色:
DBA 就是那个 分蛋糕的CEO。他需要:
- 了解每个部门(消费者组)的重要性(业务优先级)。
- 制定公平且高效的规则(资源计划)。
- 监控蛋糕分配情况(查看
V$RSRC_CONSUMER_GROUP),如果发现某个部门总是抱怨饿(等待事件激增),就要么给他们分配更大的比例(修改指令),要么去买个更大的蛋糕(增加服务器CPU)。
总结:
Oracle 资源管理器是一个极其强大的内部资源治理工具。通过消费者组、多级计划和插值算法,它实现了精细化的、动态的 CPU 资源分配。DBA 通过配置 DRM,可以有效地隔离工作负载、保障关键服务的 SLA,并在资源紧张时做出可预测的、基于策略的调度决策,从而确保数据库的整体稳定性和高效性。理解并善用 DRM,是高级 DBA 管理复杂、混合负载数据库环境的标志性技能。
欢迎关注我的公众号《IT小Chen》

被折叠的 条评论
为什么被折叠?



