はじめに

こんにちは。Oracle Databaseの検証チームです。
今回は、Oracle Database Enterprise Editionの機能である「リソース・マネージャ」でできるCPU制限の方法をご紹介いたします。

リソース・マネージャは古くからあるOracle Databaseの機能ですので、ご存じの方も多いかと思います。
しかし、「コンシューマ・グループ」とか、「ディレクティブ」とかの用語が諸々出てくるし、設定もマニュアルを読むと複雑でよくわからんと感じることも多いのではないでしょうか。

今回、ご紹介するのはDB全体で消費するCPU使用率の上限を簡単に設定する方法です。

リソース・マネージャについて

リソース・マネージャとは

DBが消費するCPUやメモリ(PGA)といったリソースを制御する機能です。
使用可能なリソースの上限を設けたり、スキーマごとに優先度を決めてリソースを配分することができます。
マルチテナント(CDB)環境では各 PDB 間のリソースを配分することもできます。

検証(リソース・マネージャ設定)

今回の検証では、「DBが消費するCPU使用率:最大70%」という内容のリソース・プランを作成し有効にします。

現在の設定状況の確認

現在有効なリソース・プランを確認します。
以下の実行例ではリソース・プランは有効化されていません。

SQL> show parameter resource_manager_plan

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
resource_manager_plan                string

リソース・プランの作成

リソース・プランを作成します。

SQL> 
BEGIN
  DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
  DBMS_RESOURCE_MANAGER.CREATE_PLAN(
    PLAN    => 'CPU_PLAN',
    COMMENT => 'Limit overall database CPU');
  DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
    PLAN              => 'CPU_PLAN',
    GROUP_OR_SUBPLAN  => 'OTHER_GROUPS',
    COMMENT           => 'This group is mandatory',
    UTILIZATION_LIMIT => 70);
  DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();
  DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
END;
/


PL/SQL procedure successfully completed.


■実行コマンドの説明

以下の箇所でリソース・プランを作成しています。
  PLAN   : リソース・プラン名を指定します。今回は「CPU_PLAN」としています。
  COMMENT: プランに対する任意のコメントです。

  DBMS_RESOURCE_MANAGER.CREATE_PLAN(
    PLAN    => 'CPU_PLAN',
    COMMENT => 'Limit overall database CPU');

以下の箇所でリソース・プランの内容を設定しています。
  PLAN         : 作成したリソース・プラン名を指定します。
  GROUP_OR_SUBPLAN: 「OTHER_GROUPS」を指定します。今回は他のコンシューマ・グループの設定は行いません。(※1)
  COMMENT       : 任意のコメントです。
  UTILIZATION_LIMIT : DBが消費できるCPU使用率(%)の上限を指定します。今回は「70%」としています。

  DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(
    PLAN              => 'CPU_PLAN',
    GROUP_OR_SUBPLAN  => 'OTHER_GROUPS',
    COMMENT           => 'This group is mandatory',
    UTILIZATION_LIMIT => 70);

※1
「GROUP_OR_SUBPLAN」には、リソース制限するスキーマを含むコンシューマグループを設定します。
ORACLEで事前に定義している「OTHER_GROUPS」は、制限対象となるコンシューマ・グループ以外の全スキーマを意味します。
「OTHER_GROUPS」以外のコンシューマ・グループを設定しないことで、制限対象がDBの全スキーマとなります。

リソース・プランの有効化

リソース・プランを有効にするために、初期化パラメータRESOURCE_MANAGER_PLANに、作成した「CPU_PLAN」を設定します。

SQL> ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'CPU_PLAN';

System altered.

設定状況の確認

現在有効化されているリソース・プランを確認します。
以下の実行例では「CPU_PLAN」が有効となっています。

SQL> show parameter resource_manager_plan

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
resource_manager_plan                string      CPU_PLAN

CPU_PLAN」の設定内容を確認します。
以下の実行例ではコンシューマ・グループ「OTHER_GROUPS」に対し、CPU使用率の上限が70%で設定されています。

SQL> SELECT PLAN,GROUP_OR_SUBPLAN,TYPE,MGMT_P1,UTILIZATION_LIMIT FROM DBA_RSRC_PLAN_DIRECTIVES WHERE PLAN='CPU_PLAN';

PLAN                           GROUP_OR_SUBPLAN     TYPE              MGMT_P1 UTILIZATION_LIMIT
------------------------------ -------------------- -------------- ---------- -----------------
CPU_PLAN                       OTHER_GROUPS         CONSUMER_GROUP          0                70

現在アクティブなリソース・プランを確認します。
以下の実行例では「CPU_PLAN」がアクティブになっています。

SQL> SELECT NAME, IS_TOP_PLAN FROM V$RSRC_PLAN;

NAME                             IS_TO
-------------------------------- -----
CPU_PLAN                         TRUE

以上で、リソース・マネージャの設定は完了です。
1回のPL/SQLの実行で簡単に設定ができました。

参考:https://docs.oracle.com/cd/G11854_01/admin/managing-resources-with-oracle-database-resource-manager.html

検証(動作確認)

DBに対してSQLで負荷を掛け、CPU使用状況とリソース・マネージャによる待機の発生状況を確認します。

確認方法

負荷掛けツールを使用して以下の実行と確認を行います。
検証環境のCPU数は「2」です。

  • 50接続を5分間実行するSQLを3端末から実行
  • 上記を1時間程度、順次実行
  • 1時間後にコンシューマ・グループ「OTHER_GROUPS」のCPU使用状況を確認
  • 1時間後に待機イベント「resmgr:cpu quantum」の発生状況を確認

■待機イベントの説明
resmgr:cpu quantum   : リソース・マネージャでCPU消費量を制限している場合に発生し、CPU割り当てを確保するために待機した時間です。

負荷テスト実行

実行中・・・

実行結果

負荷テスト後、1分間にDB(OTHER_GROUPS)が消費したCPU時間 [cpu_consumed_time(s)] を確認すると、概ね84秒以下で推移しています。
検証環境のCPU数は2のため、1分間にDBがCPU時間を消費できる上限は 84秒となります。
リソース・マネージャで設定したCPU使用率上限の70%で制限がかかり、待機が発生していることが確認できました。

SQL> 
select 
   to_char(m.begin_time, 'HH:MI') time, m.consumer_group_name, 
   m.cpu_consumed_time /1000 as "cpu_consumed_time(s)", 
   m.cpu_wait_time /1000 as "cpu_wait_time(s)"
from v$rsrcmgrmetric_history m, dba_rsrc_plan_directives d, v$rsrc_plan p 
where m.consumer_group_name = d.group_or_subplan and p.name = d.plan 
order by m.begin_time, m.consumer_group_name;

TIME  CONSUMER_GROUP_NAME            cpu_consumed_time(s) cpu_wait_time(s)
----- ------------------------------ -------------------- ----------------
05:36 OTHER_GROUPS                                 74.775          382.903
05:37 OTHER_GROUPS                                 79.955          918.337
05:38 OTHER_GROUPS                                 83.942         1251.706
05:39 OTHER_GROUPS                                 84.954          2000.18
05:40 OTHER_GROUPS                                 82.612          1647.14
05:41 OTHER_GROUPS                                 79.264          650.244
05:42 OTHER_GROUPS                                 82.367          783.372
05:43 OTHER_GROUPS                                 81.141          580.164
05:44 OTHER_GROUPS                                 84.238         1698.504
   :
  <省略>

■上記結果の説明
cpu_consumed_time(s)   : 1分間にセッションが消費したCPU時間の合計(秒)
cpu_wait_time(s)      : 1分間にセッションがCPUを待機した時間(秒)

1分間にDBが消費できるCPU時間の上限は以下で算出します。

1分間:60秒 × CPU数:2 × CPU使用率上限:70 ÷ 100 = 84秒

また、過去1時間に待機イベント「resmgr:cpu quantum」が1,036秒発生しており、
リソース・マネージャによりCPU制限がかかり、待機が発生していることも確認できました。

SQL> 
 select event,SUM(TIME_WAITED)/1000/1000 as "TIME_WAITED(s)" from v$active_session_history
 where sample_time > sysdate - 60/1440
 and event ='resmgr:cpu quantum' group by event order by event;

EVENT                                                        TIME_WAITED(s)
------------------------------------------------------------ --------------
resmgr:cpu quantum                                                1,036.473

各セッション毎でも、待機イベント「resmgr:cpu quantum」による待機状況が確認できました。

SQL> 
 select sample_time,session_id,session_serial#,event,TIME_WAITED from v$active_session_history  
  where sample_time > sysdate - 60/1440
 and event ='resmgr:cpu quantum' order by sample_time;

SAMPLE_TIME                SESSION_ID SESSION_SERIAL# EVENT 			   TIME_WAITED(マイクロ秒)
-------------------------- ---------- --------------- --------------------- ----------------------
18-DEC-24 05.44.16.254 PM	      245	    15609     resmgr:cpu quantum		    115480
18-DEC-24 05.44.16.254 PM	      249	    15440     resmgr:cpu quantum		    137315
18-DEC-24 05.44.16.254 PM	      250	    52758     resmgr:cpu quantum		    130761
18-DEC-24 05.44.16.254 PM	      251	    28334     resmgr:cpu quantum		    117044
18-DEC-24 05.44.16.254 PM	      252	    64577     resmgr:cpu quantum		     90442
18-DEC-24 05.44.16.254 PM	      253	     2753     resmgr:cpu quantum		     88696
18-DEC-24 05.44.16.254 PM	      254	     4229     resmgr:cpu quantum		    153077
18-DEC-24 05.44.16.254 PM	      256	    35824     resmgr:cpu quantum		    130353
   :
  <省略>

補足

デフォルト時に使用されるリソース・プラン

初期化パラメータ「RESOURCE_MANAGER_PLAN」を有効化していないデフォルトの状態では、「INTERNAL_PLAN」というORACLE事前定義済のプランが使用されます。

SQL> SELECT NAME, IS_TOP_PLAN FROM V$RSRC_PLAN;

NAME                             IS_TO
-------------------------------- -----
INTERNAL_PLAN                    TRUE

また、ORACLEメンテナンスタスクの実行中は「DEFAULT_MAINTENANCE_PLAN」というORACLE事前定義済のプランが使用されます。

SQL> SELECT WINDOW_NAME, RESOURCE_PLAN FROM DBA_SCHEDULER_WINDOWS;

WINDOW_NAME                RESOURCE_PLAN
-------------------------- --------------------------
MONDAY_WINDOW              DEFAULT_MAINTENANCE_PLAN
TUESDAY_WINDOW             DEFAULT_MAINTENANCE_PLAN
WEDNESDAY_WINDOW           DEFAULT_MAINTENANCE_PLAN
THURSDAY_WINDOW            DEFAULT_MAINTENANCE_PLAN
FRIDAY_WINDOW              DEFAULT_MAINTENANCE_PLAN
SATURDAY_WINDOW            DEFAULT_MAINTENANCE_PLAN
SUNDAY_WINDOW              DEFAULT_MAINTENANCE_PLAN
WEEKNIGHT_WINDOW
WEEKEND_WINDOW

SQL> SELECT PLAN,GROUP_OR_SUBPLAN,TYPE,MGMT_P1,UTILIZATION_LIMIT FROM DBA_RSRC_PLAN_DIRECTIVES WHERE PLAN='DEFAULT_MAINTENANCE_PLAN';

PLAN                           GROUP_OR_SUBPLAN     TYPE              MGMT_P1 UTILIZATION_LIMIT
------------------------------ -------------------- -------------- ---------- -----------------
DEFAULT_MAINTENANCE_PLAN       SYS_GROUP            CONSUMER_GROUP         75
DEFAULT_MAINTENANCE_PLAN       OTHER_GROUPS         CONSUMER_GROUP         20
DEFAULT_MAINTENANCE_PLAN       ORA$AUTOTASK         CONSUMER_GROUP          5                90

バックグラウンドプロセス

バックグラウンドプロセスは「_ORACLE_BACKGROUND_GROUP_」に含まれ、リソース・プランの影響を受けません。
「_ORACLE_BACKGROUND_GROUP_」はリソースマネージャーによる制限を受けない、バックグラウンドプロセス向けに事前定義されたコンシューマグループです。
これにより、CPU負荷上昇時においてもMMONプロセス等は制限されず、DBは正常に稼働を続けることができます。

おわりに

今回はDB全体で使用するCPUの上限を設定する方法をご紹介しました。

検証環境等CPU数が少ない環境でOSや他ミドルウェアが使用するCPUを確保するためなど、DBが使用するCPUを制限したい場合の選択肢の一つになるかと思います。

また、冒頭でリソース・マネージャは複雑と記述しましたが、それだけ状況に応じた詳細な設定が可能な機能です。
DBサーバのリソース管理でお悩みの際はリソース・マネージャの使用もご検討してみてはいかがでしょうか。

最後までお読みいただきありがとうございました。

お問合せはこちら

投稿者プロフィール

技術チーム
技術チーム
DBひとりでできるもんを盛り上げるべく、技術チームが立ち上がり早6年。ひとりでできるもんと言いつつ、技術者が読んでプッとなるような、極めてピンポイントでマニアックな技術ネタを執筆しています!