本記事では、主にOracleモードでのリソース分離の設定方法について説明します。
前提条件
リソース分離の設定を開始する前に、リソースグループ、リソース管理計画、リソース管理計画の内容などの基本概念を理解しておくことを推奨します。リソース分離に関連する基本概念および適用シナリオについては、リソース分離の概要を参照してください。
CPUのリソース分離はcgroupに依存しているため、CPUのリソース分離を制御する必要がある場合は、リソース分離の設定を開始する前に、cgroupディレクトリを設定し、cgroup機能を有効にする必要があります。cgroupディレクトリの設定とcgroup機能の有効化に関する操作については、cgroupの設定を参照してください。
Userレベルのリソース分離とFunctionレベルのリソース分離を設定する場合、CPUのリソース分離を制御する必要がない場合(IOPSのリソース分離のみが必要な場合)、cgroupの設定は不要です。SQLレベルのリソース分離を設定する場合は、CPUのリソース分離を制御する必要があるかどうかにかかわらず、cgroupの設定が必要です。
IOPSのリソース分離を行う前に、ディスク性能のキャリブレーションを実行できます。ディスク性能のキャリブレーションに関する操作については、ディスク性能のキャリブレーションを参照してください。
説明
現在のバージョンでは、IOPSのリソース分離はディスク性能のキャリブレーション操作に強く依存しなくなりました。
リソース分離を行うユーザーが作成済みであることを確認してください。ユーザー作成の詳細な操作については、ユーザーの作成を参照してください。
SQLレベルのリソース分離を設定する必要がある場合は、リソース分離を行うデータベース、テーブル、列が作成済みであることを確認してください。
背景
リソース分離は、Userレベルのリソース分離、SQLレベルのリソース分離、Functionレベルのリソース分離の3種類に分けられます。これら3種類のリソース分離の詳細については、リソース分離の概要を参照してください。
ステップ1(オプション):テナントのMAX_IOPSとMIN_IOPSを有効な値に設定する
説明
テナント作成時に使用したUnit仕様で、MAX_IOPSとMIN_IOPSが16KB読み取りに対応するIOPS値に設定されている場合、またはIOPSを制御するリソース分離が不要な場合は、この手順を無視してください。
ディスクキャリブレーションが完了した後、リソース分離計画を設定する前に、テナントのリソース仕様におけるMAX_IOPSとMIN_IOPSの値が有効であることを確認する必要があります。ここでの有効な値とは、16KB読み取りに対応するIOPS値をテナントのIOPS設定の参考値とすることを指します。
rootユーザーでクラスタのsysテナントにログインします。以下のコマンドを実行し、リソース分離を行うテナントのリソース仕様を確認します。
obclient [oceanbase]> SELECT * FROM oceanbase.DBA_OB_UNIT_CONFIGS;クエリ結果の例は以下のとおりです:
+----------------+-----------------+----------------------------+----------------------------+---------+---------+-------------+---------------+---------------------+---------------------+-------------+ | UNIT_CONFIG_ID | NAME | CREATE_TIME | MODIFY_TIME | MAX_CPU | MIN_CPU | MEMORY_SIZE | LOG_DISK_SIZE | MAX_IOPS | MIN_IOPS | IOPS_WEIGHT | +----------------+-----------------+----------------------------+----------------------------+---------+---------+-------------+---------------+---------------------+---------------------+-------------+ | 1 | sys_unit_config | 2023-12-19 13:55:04.463295 | 2023-12-19 13:56:08.969718 | 3 | 3 | 2147483648 | 3221225472 | 9223372036854775807 | 9223372036854775807 | 3 | | 1001 | small_unit | 2023-12-19 13:56:09.851665 | 2023-12-19 13:56:09.851665 | 1 | 1 | 2147483648 | 6442450944 | 9223372036854775807 | 9223372036854775807 | 1 | | 1002 | medium_unit | 2023-12-19 13:56:10.030914 | 2023-12-19 13:56:10.030914 | 8 | 4 | 8589934592 | 25769803776 | 9223372036854775807 | 9223372036854775807 | 4 | | 1003 | large_unit | 2023-12-19 13:56:10.112115 | 2023-12-19 13:56:10.112115 | 16 | 8 | 21474836480 | 64424509440 | 9223372036854775807 | 9223372036854775807 | 8 | +----------------+-----------------+----------------------------+----------------------------+---------+---------+-------------+---------------+---------------------+---------------------+-------------+ 4 rows in setクエリ結果によると、当該テナントの
MAX_IOPSとMIN_IOPSがどちらもデフォルト値INT64_MAX(9223372036854775807)である場合、テナントが利用可能なIOPSリソースを再計画する必要があります。以下のコマンドを実行し、テナントがデプロイされているOBServerノードを確認します。
obclient [oceanbase]> SELECT DISTINCT SVR_IP, SVR_PORT FROM oceanbase.CDB_OB_LS_LOCATIONS WHERE tenant_id = xxxx;クエリ結果の例は以下のとおりです:
+----------------+----------+ | SVR_IP | SVR_PORT | +----------------+----------+ | xx.xxx.xxx.xx1 | xxxx1 | | xx.xxx.xxx.xx1 | xxxx2 | | xx.xxx.xxx.xx1 | xxxx3 | +----------------+----------+ 3 rows in set以下のコマンドを実行し、リソース分離を行うテナントが配置されているOBServerノード上のディスクキャリブレーション値を確認します。16KB読み取りのディスクキャリブレーション値をそのノードのIOPS設定の上限値として使用します。
obclient [oceanbase]> SELECT * FROM oceanbase.GV$OB_IO_BENCHMARK WHERE MODE='READ' AND SIZE=16384;クエリ結果の例は以下のとおりです:
+----------------+----------+--------------+------+-------+-------+------+---------+ | SVR_IP | SVR_PORT | STORAGE_NAME | MODE | SIZE | IOPS | MBPS | LATENCY | +----------------+----------+--------------+------+-------+-------+------+---------+ | xx.xxx.xxx.xx1 | xxxx1 | DATA | READ | 16384 | 48162 | 752 | 331 | | xx.xxx.xxx.xx1 | xxxx2 | DATA | READ | 16384 | 47485 | 741 | 336 | | xx.xxx.xxx.xx1 | xxxx3 | DATA | READ | 16384 | 48235 | 753 | 331 | +----------------+----------+--------------+------+-------+-------+------+---------+ 3 rows in setクエリ結果に基づき、取得した各ノードのディスクキャリブレーション値を上限値としてテナントが利用可能なIOPSを計画します。クラスタ内に複数のテナントが同一のOBServerノードにデプロイされている可能性があるため、業務の実際の状況に応じてこれらのIOPSを割り当てることができます。
あるクラスタに2つのテナントがあり、両方のテナントが同一のOBServerノードにデプロイされている場合、各OBServerノードの16KB読み取りのディスクIOPSベース値が同じで20000 IOPSであり、かつ、2つのテナントの負荷がほぼ同じであると予想される場合、20000 IOPSを2つのテナントに均等に分割することができます(具体的には、実際の業務状況に応じてテナントが利用可能なIOPSを割り当てることができます)。つまり、各テナントの
MAX_IOPSとMIN_IOPSを10000に設定します。業務上の理由から、MIN_IOPSをMAX_IOPSより小さい値に設定することもできます。以下のコマンドを実行し、テナントの
MAX_IOPSとMIN_IOPS値を変更します。MIN_IOPSを変更してからMAX_IOPSを変更することを推奨します。ALTER RESOURCE UNIT unit_name MIN_IOPS = xxx;ALTER RESOURCE UNIT unit_name MAX_IOPS = xxx;
ステップ2:リソース分離計画を設定する
現在のテナントに既に tp_user と ap_user の2つのユーザーが存在すると仮定します。
以下の手順を参考に、リソース分離計画を設定して、異なるユーザーやバックグラウンドタスクが使用するCPUまたはIOPSリソースを制御できます。
テナント管理者がクラスタのOracleテナントにログインします。
DBMS_RESOURCE_MANAGERシステムパッケージのCREATE_CONSUMER_GROUPサブプログラムを呼び出し、リソース分離に必要な2つのリソースグループを作成します。ステートメントは以下のとおりです:
BEGIN DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP( consumer_group => 'group_name' , COMMENT => 'coments' ); END;関連パラメータの説明は以下のとおりです:
CONSUMER_GROUP:リソースグループ名を定義します。COMMENT:リソースグループの備考情報を入力します。
例えば、以下の2つのリソースグループ
big_groupとsmall_groupを作成します。obclient [SYS]> delimiter //obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP( consumer_group => 'big_group' , COMMENT => 'TP' ); END; //obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP( consumer_group => 'small_group' , COMMENT => 'AP' ); END; //作成が成功した後、
DBA_RSRC_CONSUMER_GROUPSビューを確認することができます。DBA_RSRC_CONSUMER_GROUPSビューの詳細については、DBA_RSRC_CONSUMER_GROUPSを参照してください。DBMS_RESOURCE_MANAGERシステムパッケージのCREATE_PLANサブプログラムを呼び出し、リソース管理計画を作成します。ステートメントは以下のとおりです:
BEGIN DBMS_RESOURCE_MANAGER.CREATE_PLAN( PLAN => 'plan_name', COMMENT =>'coments' ); END;関連パラメータの説明は以下のとおりです:
PLAN:リソース管理計画名を定義します。COMMENT:リソース管理計画の備考情報を入力します。
例えば、
plan_aという名前のリソース管理計画を作成します。obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.CREATE_PLAN( PLAN => 'plan_a'); END; //作成が成功した後、
DBA_RSRC_PLANSビューを確認することができます。DBA_RSRC_PLANSビューの詳細については、DBA_RSRC_PLANSを参照してください。DBMS_RESOURCE_MANAGERシステムパッケージのCREATE_PLAN_DIRECTIVEサブプログラムを呼び出し、リソース管理計画に対応するリソース管理計画内容を作成します。これは、リソース管理計画を有効化する際に、リソースグループが使用するCPUリソースとIOPSリソースを制限するために使用されます。ステートメントは以下のとおりです:
BEGIN DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE( PLAN => 'plan_name', GROUP_OR_SUBPLAN => 'group_name', COMMENT => 'comments', MGMT_P1 => int_value, UTILIZATION_LIMIT => int_value, MIN_IOPS => int_value, MAX_IOPS => int_value, WEIGHT_IOPS => int_value, MAX_NET_BANDWIDTH => int_value, NET_BANDWIDTH_WEIGHT => int_value); END;関連パラメータの説明は以下のとおりです:
PLAN:このリソース管理計画内容に関連付けるリソース管理計画名を指定します。GROUP_OR_SUBPLAN:リソースグループを指定します。COMMENT:リソース管理計画内容の備考情報を入力します。デフォルト値はNULLです。MGMT_P1:システムがフル負荷の場合の相対的に利用可能な最大CPU割合を指定します。デフォルト値は100です。UTILIZATION_LIMIT:リソースグループが使用するCPUリソースの上限を指定します。このパラメータのデフォルト値は100で、取り得る範囲は (0, 100] です。100はテナントの全CPUリソースを最大限に使用できることを意味します。値を40に設定すると、テナントのCPUリソースの40%を最大限に使用できます。MIN_IOPS:I/O競合が発生した場合に、リソースグループが予約するIOPSリソースです。合計は100を超えません。デフォルト値は0です。MAX_IOPS:リソースグループが使用できる最大IOPSリソースを指定します。合計は100を超えることができます。デフォルト値は100です。WEIGHT_IOPS:IOPSの重み値を指定します。合計は100を超えることができます。デフォルト値は0です。MAX_NET_bandWIDTH:使用できる最大ネットワーク帯域幅リソースを指定します。合計は100を超えることができます。デフォルト値は100です。NET_BANDWIDTH_WEIGHT:ネットワーク帯域幅の重み値を指定します。合計は100を超えることができます。比率に応じて分割されます。デフォルト値は0です。
例:
リソース計画を
plan_aに指定し、リソースグループbig_groupにバインドします。使用可能なCPUリソースの上限をテナントCPU総リソースの60%に設定します。同時に、I/O競合が発生した場合、使用可能なIOPSリソースの最小割合を20%、使用可能なIOPSリソースの上限をIOPS総リソースの100%、IOPSリソースの重みを20》、使用可能なネットワーク帯域幅リソースを50%、ネットワーク帯域幅の重みを50%に指定します。obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE( PLAN => 'plan_a', GROUP_OR_SUBPLAN => 'big_group', COMMENT => 'TP優先', UTILIZATION_LIMIT =>60, MIN_IOPS => 20, MAX_IOPS => 100, WEIGHT_IOPS => 20, MAX_NET_BANDWIDTH => 50, NET_BANDWIDTH_WEIGHT =>50); END; //リソース計画を
plan_aに指定し、リソースグループsmall_groupにバインドします。使用可能なCPUリソースの上限をテナントCPU総リソースの40%に設定します。同時に、I/O競合が発生した場合、使用可能なIOPSリソースの最小割合を10%、使用可能なIOPSリソースの上限をIOPS総リソースの90%、IOPSリソースの重みを30》、使用可能なネットワーク帯域幅リソースを60%、ネットワーク帯域幅の重みを60%に指定します。obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE( PLAN => 'plan_a', GROUP_OR_SUBPLAN => 'small_group' , COMMENT => 'AP優先', UTILIZATION_LIMIT =>40, MIN_IOPS => 10, MAX_IOPS => 90, WEIGHT_IOPS => 30, MAX_NET_BANDWIDTH => 60, NET_BANDWIDTH_WEIGHT =>60); END; //
作成が成功したら、
DBA_RSRC_PLAN_DIRECTIVESビューとDBA_OB_RSRC_IO_DIRECTIVESビューを確認することができます。DBA_RSRC_PLAN_DIRECTIVESビューの詳細については、DBA_RSRC_PLAN_DIRECTIVESを参照してください。DBA_OB_RSRC_IO_DIRECTIVESビューの詳細については、DBA_OB_RSRC_IO_DIRECTIVESを参照してください。DBMS_RESOURCE_MANAGERシステムパッケージのSET_CONSUMER_GROUP_MAPPINGサブプログラムを呼び出し、実際の使用シナリオに基づいて、リソース分離のマッピングルールを作成します。ステートメントは以下のとおりです:
BEGIN DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( ATTRIBUTE => 'column | user | function', VALUE => 'values', CONSUMER_GROUP => 'group_name'); END;関連パラメータの説明は以下のとおりです:
ATTRIBUTE:属性タイプを指定します。属性名は大文字小文字を区別しません。columnはSQLレベルのリソース分離を表します。userはUserレベルのリソース分離を表します。functionはFunctionレベルのリソース分離を表します。
VALUE:属性値を指定します。属性タイプが
columnの場合、データベース名、テーブル名、列名、定数値、ユーザー名などの情報を指定する必要があります。その中で:
データベース名とユーザー名はオプションです。デフォルトのデータベース名は現在のデータベース名(ユーザー名と同じ)です。ユーザー名が指定されていない場合、現在のテナント内で後から作成されるすべてのユーザーに適用されます。
テーブル名、列名、定数値は必須項目であり、各項目には1つの値のみを指定できます。定数値を指定する場合、数値または文字列のみを指定できます。
テーブル名、列名、ユーザー名を指定する場合、指定されたテーブル、列、ユーザーが存在している必要があります。
OceanBaseデータベースのOracleモードでは、ステートメントの実行が成功すると、データベース名、テーブル名、列名、ユーザー名は自動的に大文字に変更されます。小文字のままに保ちたい場合は、二重引用符を追加することで大文字になるのを防ぐことができます。例:
obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( ATTRIBUTE => 'column', VALUE => '"test"."t1"."c3" = 3 for "user_big"', CONSUMER_GROUP => 'big_group'); END; //属性タイプが
userの場合、ここにユーザー名を指定するだけで済みます。現在は1人のユーザーのみを指定できます。属性タイプが
functionの場合、ここでDAGスレッドに対応するいくつかのバックグラウンドタスクを指定します:compaction_high、ha_high、compaction_mid、ha_mid、compaction_low、ha_low、ddl、ddl_high、clog_high、およびopt_stats。そのうちの1つを記入します。現在は1つのタスクのみを指定できます。各タスクの詳細については、リソース分離の概要を参照してください。
CONSUMER_GROUP:バインドするリソースグループを指定します。SQLがVALUEで設定されたマッチングルールにヒットした場合、そのステートメントを実行するためにどのリソースグループにバインドするかを示します。現在は1つのリソースグループのみをバインドできます。バインドするリソースグループを指定しない場合、デフォルトでシステム組み込みの
OTHER_GROUPSにバインドされます。システム組み込みのOTHER_GROUPSが対応するリソースは以下のとおりです:MIN_IOPS = 100 - SUM(テナント内の他のリソースグループの合計)
MAX_IOPS = 100
WEIGHT_IOPS = 100
例:
SQLレベルのリソース分離マッチングルールを作成します。
ユーザー
tp_userが実行するWHERE条件にsys.t.c3 = 3を含むSQLステートメントが指定された場合、そのSQLステートメントはbig_groupという名前のリソースグループにバインドされて実行され、そのリソースグループによって制限されたCPUリソースとIOPSリソースが使用されます。注意
SQLステートメントを実行する際、ステートメントに
sys.t.が含まれている必要はありません。c3が最終的にsys.t.c3として解釈されれば、そのSQLステートメントはbig_groupという名前のリソースグループにバインドされて実行されます。例:SELECT * FROM sys.t WHERE c3 = 1;。obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( ATTRIBUTE => 'column', VALUE => 'sys.t.c3=3 for tp_user', CONSUMER_GROUP => 'big_group'); END; //実行する
WHERE条件にt.c3=5を含むSQLステートメントが指定された場合、そのSQLステートメントはsmall_groupという名前のリソースグループにバインドされて実行され、そのリソースグループによって制限されたCPUリソースとIOPSリソースが使用されます。obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( ATTRIBUTE => 'column', VALUE => 't.c3=5', CONSUMER_GROUP => 'small_group'); END; //
SET_CONSUMER_GROUP_MAPPINGサブプログラムを呼び出してリソースグループをバインドする方法以外に、OceanBaseデータベースではHintを使用してリソースグループをバインドする方法もサポートしています。ユーザーはHintを使用することで、実行待ちのSQLを指定したリソースグループに柔軟に送信できます。例えば、実行待ちのSQLステートメントがSELECT * FROM Tで、そのSQLステートメントがリソースグループbig_groupによって制限されたリソースを使用することを望む場合、Hintを使用して対応するリソースグループにバインドする例は以下のとおりです:obclient [SYS]> SELECT /*+resource_group('big_group')*/ * FROM T;説明
Hintを使用してリソースグループを指定した後、リソースグループが存在しない場合、ステートメントの実行時にはデフォルトのリソースグループ
OTHER_GROUPSが使用されます。Userレベルのリソース分離マッチングルールを作成します。
ユーザー
tp_userが実行するSQLをbig_groupという名前のリソースグループにバインドして実行し、そのリソースグループによって制限されたCPUリソースとIOPSリソースを使用します。obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( ATTRIBUTE => 'user', VALUE => 'tp_user', CONSUMER_GROUP => 'big_group'); END; //ユーザー
ap_userが実行するSQLをsmall_groupという名前のリソースグループにバインドして実行し、そのリソースグループによって制限されたCPUリソースとIOPSリソースを使用します。obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( ATTRIBUTE => 'user', VALUE => 'ap_user', CONSUMER_GROUP => 'small_group'); END; //
Functionレベルのリソース分離マッチングルールを作成します。
ha_highのタスクを実行する際、システムがbig_groupという名前のリソースグループにバインドされて実行され、そのリソースグループによって制限されたCPUリソースとIOPSリソースを使用します。obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( ATTRIBUTE => 'function', VALUE => 'ha_high', CONSUMER_GROUP => 'big_group'); END; //ddl_highのタスクを実行する際、システムがsmall_groupという名前のリソースグループにバインドされて実行され、そのリソースグループによって制限されたCPUリソースとIOPSリソースを使用します。obclient [SYS]> BEGIN DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( ATTRIBUTE => 'function', VALUE => 'ddl_high', CONSUMER_GROUP => 'small_group'); END; //
作成が成功した後、
DBA_RSRC_GROUP_MAPPINGSビューを確認することができます。DBA_RSRC_GROUP_MAPPINGSビューの詳細については、DBA_RSRC_GROUP_MAPPINGSを参照してください。リソースグループに適切なリソース管理計画を有効にします。
異なるリソース管理計画では、同一のリソースグループが制限されるリソースが異なる場合があります。リソースグループに適切なリソース管理計画を有効にする必要があります。
obclient [SYS]>delimiter ;obclient [SYS]> ALTER SYSTEM SET resource_manager_plan = 'plan_a';説明
リソースを制限する必要がない場合は、
ALTER SYSTEM SET resource_manager_plan = '';ステートメントを使用してすべてのリソース計画を無効にできます。
設定後の注意事項
リソース分離マッチングルールを追加した後、ユーザーを削除して再作成しても、リソース分離マッチングルールは引き続き適用されます。
リソース分離マッチングルールは追加後すぐには有効にならず、通常は10秒以内に反映されますが、実際の環境によって異なる場合があります。
SQLレベルのリソース分離は、UserレベルおよびFunctionレベルのリソース分離よりも優先順位が高いです。
リソース分離マッチングルールを追加した後、現在は
SELECT、INSERT、UPDATE、DELETEなどのステートメントでのみ有効であり、DDLやDCLステートメント、PLステートメントでは有効になりません。prepareStatementでは有効になります。
設定後のパフォーマンスへの影響
UserレベルおよびFunctionレベルのリソース分離は、SQLが解析される前にどのリソースグループのリソースを使用するかを確認できるため、パフォーマンスに影響しません。
SQLレベルのリソース分離によるパフォーマンスへの影響は、主に再試行によるものです。UserレベルおよびFunctionレベルのリソース分離は、1つのSQLが解析される前にどのリソースグループのリソースを使用するかが決定されるのとは異なり、SQLレベルのリソース分離では、SQLが解析されたりPlan Cacheにヒットしたりした時点で、どのリソースグループのリソースを使用するかが決定されます。その際、使用すべきリソースグループが現在使用中のものと異なる場合、システムは一度再試行を行い、マッチングルールに対応するリソースグループのリソースを使用してそのSQLを処理します。
SQLレベルのリソース分離によるパフォーマンスへの影響は、主に以下の3つのケースに分けられます:
あるSQLがいずれのルールにもマッチしない場合、パフォーマンスにほとんど影響しません。
あるSQLが1つのルールにマッチする場合、そのルールで指定されたリソースグループが
big_groupであると仮定します。この場合、そのSQLは最終的にbig_groupのリソースで実行されるだけでなく、次のSQLも最初はbig_groupのリソースで実行されます。ルールにマッチして他のリソースグループへの切り替えが必要であることが判明するまで、システムは再試行を行いません。連続して一括処理される一連のSQLがすべて同じリソースグループにバインドされているシナリオでは、このポリシーを使用することで、最初のSQLを処理する際にのみ再試行が必要となり、後続のSQLは再試行が不要になります。これにより再試行が大幅に削減され、パフォーマンスへの影響は小さくなります。各SQLが想定して使用するリソースグループが前のSQLと毎回異なる場合、各SQLは1回ずつ再試行が必要となり、パフォーマンスへの影響は大きくなります。