【Oracle Database】Database Resource Manager検証

こちらを参考に
[Oracle® Database管理者ガイド 12cリリース1 (12.1) - 27 Oracle Database Resource Managerを使用したリソースの管理](https://docs.oracle.com/cd/E57425_01/121/ADMIN/dbrm.htm#GUID-EF88A167-74C2-482A-BA44-2E14F6091411)

## Oracle Database Resource Managerとは
>Oracle Database Resource Manager (リソース・マネージャ)を使用すると、システム・リソースやデータベース・リソースを求めて競合するデータベース内の複数のワークロードを管理できます。

ざっくりいうとDBが使用するリソースを制御できるOracle Databaseの機能

Enterprise Editionのみ使用可能で8iから導入されている

今回はCPUの制御についてざっくりと記載する。

##予備知識
###リソース・マネージャの要素について
リソース・コンシューマ・グループ：管理したい対象を１まとめにしたグループ。ユーザーやサービスなどをマッピングして管理対象としてグループに紐付ける。
リソース・プラン：リソース制御のルールを紐付けるプラン。実際の細かい制御方法はディレクティブで設定するので、リソース制御設定（ディレクティブ）と対象（コンシューマグループ）を管理する箱だと思えば良い。プランを切り替えることで、日中帯の優先度、夜間の優先度切替えなど、高度な運用ができる。
リソース・プラン・ディレクティブ：各コンシューマ・グループごとのリソース使用率を定義するルール。
ペンディング・エリア：リソース・プランを作成するときに使用する一時的な場所。
Maximum Utilization Limit：コンシューマ・グループごとに CPU リソースの使用率の上限を指定可能
インスタンス・ケージング：CPU_COUNT パラメータを使用して、インスタンスごとに CPU リソースの使用率を制限可能



##検証１．何も制御をかけなかった場合の動作
###セッションとプロセスIDを確認

```
SQL> conn unoki/unoki
Connected.

SQL> select sid, pid, spid, s.username, osuser, s.program from v$process p, v$session s where p.addr=s.paddr and s.PROGRAM like '%sqlplus%';

       SID        PID SPID                     USERNAME                       OSUSER                         PROGRAM
---------- ---------- ------------------------ ------------------------------ ------------------------------ ------------------------------------------------
       166         38 22484                    UNOKI                          oracle                         sqlplus@test.jp.test.com (TNS V1-V3)
        90         43 32294                    SYS                            oracle                         sqlplus@test.jp.test.com (TNS V1-V3)
```

SIDは166、SPIDは22484

###高CPU処理実行
バズ・ライトイヤー並にカウントアップを無限の彼方へさあ行こう、させる

```
SQL> DECLARE
  2     i NUMBER;
  3  BEGIN
  4     WHILE (1=1) LOOP
  5             i := i + 1;
  6             IF i > 1000000 THEN
  7                     i := 0;
  8             END IF;
  9     END LOOP;
 10  END;
 11  /
```

TOPで確認してみる

```
top - 17:00:35 up 70 days, 21:59,  4 users,  load average: 1.63, 1.30, 1.38
Tasks: 333 total,   2 running, 330 sleeping,   0 stopped,   1 zombie
Cpu(s): 18.0%us,  1.1%sy,  0.0%ni, 79.5%id,  0.9%wa,  0.0%hi,  0.0%si,  0.5%st
Mem:  12320264k total, 10203968k used,  2116296k free,   407472k buffers
Swap:  6152492k total,     2016k used,  6150476k free,  5560928k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
22484 oracle    20   0 2249m  49m  44m R 99.5  0.4   0:43.98 oracle_22484_or
16705 oracle    -2   0 2244m  19m  17m S  2.3  0.2  35:02.72 ora_vktm_orcl1
```
PID 22484がぶん回っていることが確認できる。

###検証２．リソース・プランを有効化した場合
今回はoltpというユーザーを作成して、CPUを75%に制御したプランで検証する

まず検証に際して専用のユーザーを作成する

```
SQL> create user res_manager identified by oracle;

User created.

SQL> grant connect to res_manager;

Grant succeeded.

SQL> BEGIN
  2    DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SYSTEM_PRIVILEGE(
   GRANTEE_NAME   => '  3  ^C

SQL> BEGIN
  2    DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SYSTEM_PRIVILEGE(
  3  GRANTEE_NAME   => 'res_manager',
  4     PRIVILEGE_NAME => 'ADMINISTER_RESOURCE_MANAGER',
  5     ADMIN_OPTION   => FALSE);
  6  END;
  7  /

PL/SQL procedure successfully completed.
```

ユーザーの作成

```
SQL> create user oltp identified by oltp;

User created.

SQL> grant connect to oltp;　--ずるした

Grant succeeded. 
```

下記のコマンドでリソースプランを一括して作成

```
BEGIN
  DBMS_RESOURCE_MANAGER.CLEAR_PENDING_AREA(); -- ペンディングエリアのクリア
  DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA(); -- ペンディングエリアの作成
   -- コンシューマ・グループの作成
  DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP (
    CONSUMER_GROUP => 'OLTP',
    COMMENT        => 'OLTP applications');

   -- OLTPユーザーとOLTPコンシューマ・グループのマッピング
  DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING (
    DBMS_RESOURCE_MANAGER.ORACLE_USER, 'OLTP', 'OLTP');

   -- リソース・プランの作成
  DBMS_RESOURCE_MANAGER.CREATE_PLAN(
    PLAN    => 'OLTP_PLAN',
    COMMENT => 'More resources for OLTP applications');

   -- リソース・プラン・ディレクティブの作成
  DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE (
   PLAN              => 'OLTP_PLAN',
   GROUP_OR_SUBPLAN  => 'OLTP',
   COMMENT           => 'OLTP group',
   UTILIZATION_LIMIT => 75);

   -- リソース・プラン・ディレクティブの作成
　 -- マッピングで定義した以外の処理(OTHER_GROUPS)に対してのディレクティブ設定は必須
  DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE (
   PLAN              => 'OLTP_PLAN',
   GROUP_OR_SUBPLAN  => 'OTHER_GROUPS',
   COMMENT           => 'Other group',
   UTILIZATION_LIMIT => 25);

   -- ペンディング・エリアの発行
  DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
END;
/

-- 作成したプランを有効化
ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'OLTP_PLAN';
```

では、実行

```
top - 17:20:50 up 70 days, 22:20,  4 users,  load average: 1.50, 1.35, 1.45
Tasks: 335 total,   2 running, 332 sleeping,   0 stopped,   1 zombie
Cpu(s): 12.7%us,  0.7%sy,  0.0%ni, 84.5%id,  1.5%wa,  0.0%hi,  0.1%si,  0.5%st
Mem:  12320264k total, 10213276k used,  2106988k free,   407492k buffers
Swap:  6152492k total,     2016k used,  6150476k free,  5553592k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
30915 oracle    20   0 2249m  32m  28m R 69.4  0.3   0:09.64 oracle_30915_or
 3410 grid      20   0  616m  75m  15m S  2.3  0.6   2278:31 gipcd.bin
```

だいたい75%付近でCPU使用率が推移している

ではその他のユーザーではどうか

```
SQL> conn unoki/unoki
Connected.
SQL> DECLARE
  i NUMBER;
BEGIN
        WHILE (1=1) LOOP
                i := i + 1;
                IF i > 1000000 THEN
                        i := 0;
                END IF;
        END LOOP;
END;
```

TOP

```
top - 17:22:14 up 70 days, 22:21,  4 users,  load average: 1.39, 1.36, 1.44
Tasks: 335 total,   1 running, 333 sleeping,   0 stopped,   1 zombie
Cpu(s):  4.5%us,  1.1%sy,  0.0%ni, 91.1%id,  2.7%wa,  0.0%hi,  0.0%si,  0.6%st
Mem:  12320264k total, 10212996k used,  2107268k free,   407496k buffers
Swap:  6152492k total,     2016k used,  6150476k free,  5553964k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
31261 oracle    20   0 2248m  31m  27m S 20.9  0.3   0:01.34 oracle_31261_or
 3410 grid      20   0  616m  75m  15m S  2.3  0.6   2278:33 gipcd.bin
```

だいたい25%以下で推移している

ちなみにリソース・マネージャによって制御が発生した場合はresmgr:cpu quantumという待機が発生する

```
17:23:06 SQL> select INST_ID,SESSION_ID,SQL_ID,MODULE,EVENT from gv$active_session_history where SAMPLE_TIME > TO_DATE('2019/04/02 17:22:54','yyyy/mm/dd hh24:mi:ss') and session_id ='166';

   INST_ID SESSION_ID SQL_ID        MODULE                                                           EVENT
---------- ---------- ------------- ---------------------------------------------------------------- ----------------------------------------------------------------
         1        166 gqucc4uk7yymd SQL*Plus                                                         resmgr:cpu quantum
         1        166 gqucc4uk7yymd SQL*Plus                                                         resmgr:cpu quantum
         1        166 gqucc4uk7yymd SQL*Plus                                                         resmgr:cpu quantum
         1        166 gqucc4uk7yymd SQL*Plus
         1        166 gqucc4uk7yymd SQL*Plus                                                         resmgr:cpu quantum

5 rows selected.
```

マッピングの優先順位も下記のようにつけれるみたいなので、次回検証したい（多分）

``` 
BEGIN
  DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING_PRI(
    EXPLICIT => 1,
    SERVICE_MODULE_ACTION => 2,
    SERVICE_MODULE => 3,
    MODULE_NAME_ACTION => 4,
    MODULE_NAME => 5,
    SERVICE_NAME => 6,
    ORACLE_USER => 7,
    CLIENT_PROGRAM => 8,
    CLIENT_OS_USER => 9,
    CLIENT_MACHINE => 10,
    CLIENT_ID => 11);
END;
/
```