2025年9月2日火曜日

SQLclのMCPサーバーが発行するSQLの実行をリソース・マネージャで制限する

更新:2026年3月26日 - プランを作成するスクリプトの共通化

SQLclのMCPサーバーは、LLMが生成したSQLを接続先のデータベースで実行します。LLMはユーザーが与えたプロンプトをもとにSQLを生成しますが、データベースに過剰な負荷をかけるSQLが生成されない保証はありません。

Oracle Databaseが提供している機能のひとつにリソース・マネージャがあります。MCPサーバーからのデータベース接続に対してリソース・マネージャによるリソースの制御を有効にすることにより、過度にCPU負荷やIO負荷が高いSQLを中断することができます。

以下より記事「Oracle Database 19c EEにEntra IDでユーザー認証してReal Application Securityを適用する」で作成した環境を使って、処理時間の長いSQLを中断するようにリソース・マネージャを構成してみます。リソース・マネージャを構成するデータベースのSIDORCL、PDBとしてORCLPDB1が作成されています。

MCPサーバーから実行されたSQLの処理時間が20秒を超えたところで、処理を中断するように構成します。

MCPサーバーはPDBのORCLPDB1に接続します。そのため、処理を中断する構成はPDBに対して行ないます。ただし、PDBに対してリソース・マネージャを構成する場合、CDBでもリソース・マネージャを有効にする必要があります。


CDBの構成



最初にCDBに接続して作業します。

sql sys@localhost/orcl as sysdba
 

% sql sys@localhost/orcl as sysdba


SQLcl: 木 3月 26 18:07:14 2026のリリース25.4 Production


Copyright (c) 1982, 2026, Oracle.  All rights reserved.


パスワード (**********?) ******

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> show parameter resource_manager_plan

NAME                  TYPE   VALUE 

--------------------- ------ ----- 

resource_manager_plan string       

SQL> 


CDBに設定されているリソース・マネージャ・プランを確認します。

show parameter resource_manager_plan

VALUEは空白なので、リソース・マネージャ・プランは未適用です。

SQL> show parameter resource_manager_plan

NAME                  TYPE   VALUE 

--------------------- ------ ----- 

resource_manager_plan string       

SQL> 


念の為、V$RSRC_PLANビューも確認します。

select name, is_top_plan, cpu_managed from v$rsrc_plan where is_top_plan = 'TRUE';

SQL> select name, is_top_plan, cpu_managed from v$rsrc_plan where is_top_plan = 'TRUE';


NAME                     IS_TOP_PLAN    CPU_MANAGED    

________________________ ______________ ______________ 

ORA$INTERNAL_CDB_PLAN    TRUE           OFF            

INTERNAL_PLAN            TRUE           OFF            

INTERNAL_PLAN            TRUE           OFF            


SQL> 


CDBについてはリソース・マネージャ・プランが設定されていればよいので、デフォルトで作成されているDEFAULT_CDB_PLANを、リソース・マネージャ・プランとして設定します。

DEFAULT_CDB_PLANの有無を確認します。

select * from dba_cdb_rsrc_plans;

SQL> select * from dba_cdb_rsrc_plans;


   PLAN_ID PLAN                        COMMENTS                        STATUS    MANDATORY    

__________ ___________________________ _______________________________ _________ ____________ 

     20248 DEFAULT_CDB_PLAN            Default CDB plan                          YES          

     20251 ORA$QOS_CDB_PLAN            QOS CDB plan                              YES          

     20250 ORA$INTERNAL_CDB_PLAN       Internal CDB plan                         YES          

     20249 DEFAULT_MAINTENANCE_PLAN    Default CDB maintenance plan              YES          


SQL> 


CDBのリソース・マネージャ・プランとして、DEFAULT_CDB_PLANを設定します。

alter system set resource_manager_plan = 'DEFAULT_CDB_PLAN' scope=both;

SQL> alter system set resource_manager_plan = 'DEFAULT_CDB_PLAN' scope=both;


Systemが変更されました。


SQL> 


再度、リソース・マネージャ・プランを表示し、CDBにリソース・マネージャ・プランが設定されたことを確認します。

SQL> show parameter resource_manager_plan

NAME                  TYPE   VALUE            

--------------------- ------ ---------------- 

resource_manager_plan string DEFAULT_CDB_PLAN 

SQL> select name, is_top_plan, cpu_managed from v$rsrc_plan where is_top_plan = 'TRUE';


NAME                IS_TOP_PLAN    CPU_MANAGED    

___________________ ______________ ______________ 

DEFAULT_CDB_PLAN    TRUE           ON             

INTERNAL_PLAN       TRUE           ON             

INTERNAL_PLAN       TRUE           ON             


SQL> 


CDBのリソース・マネージャ・プランとして、DEFAULT_CDB_PLANが設定されました。


PDBの構成



続いて、PDBのリソース・マネージャ・プランを構成します。

ORCLPDB1に接続して作業します。

sql sys@localhost/orclpdb1 as sysdba

% sql sys@localhost/orclpdb1 as sysdba


SQLcl: 木 3月 26 18:14:34 2026のリリース25.4 Production


Copyright (c) 1982, 2026, Oracle.  All rights reserved.


パスワード (**********?) ******

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> 


PDBに設定されているリソース・マネージャ・プランを確認します。

show parameter resource_manager_plan

VALUEは空白なので、リソース・マネージャ・プランは未適用です。

SQL> show parameter resource_manager_plan

NAME                  TYPE   VALUE 

--------------------- ------ ----- 

resource_manager_plan string       

SQL> 


コンシューマ・グループとしてRESTRICT_RUNAWAY、リソース・マネージャ・プランとしてMY_PDB_PLANを作成し、経過時間の上限を20秒CPU時間の上限を10秒として、SQLを中断するプラン・ディレクティブを作成します。

作成したコンシューマ・グループRESTRICT_RUNAWAYを、MCPサーバーの接続ユーザーMCPUSERが使用できるように権限を与えます。
begin
  dbms_resource_manager_privs.grant_switch_consumer_group ( 
    grantee_name => 'MCPUSER', 
    consumer_group => 'RESTRICT_RUNAWAY', 
    grant_option => FALSE
  );
end;
/

SQL> @create_RESTRICT_RUNAWAY.sql 

resource consumer group created RESTRICT_RUNAWAY

resource manager plan created MY_PDB_PLAN

plan directives created RESTRICT_RUNAWAY for MY_PDB_PLAN

default plan directive created OTHER_GROUPS for MY_PDB_PLAN

pending area submitted successfully.



PL/SQLプロシージャが正常に完了しました。


SQL> begin

  2    dbms_resource_manager_privs.grant_switch_consumer_group ( 

  3      grantee_name => 'MCPUSER', 

  4      consumer_group => 'RESTRICT_RUNAWAY', 

  5      grant_option => FALSE

  6    );

  7  end;

  8* /


PL/SQLプロシージャが正常に完了しました。


SQL> 


ビューを検索して設定を確認します。

プランMY_PDB_PLANの存在を確認します。

select * from dba_rsrc_plans where plan = 'MY_PDB_PLAN';

SQL> select * from dba_rsrc_plans where plan = 'MY_PDB_PLAN';


   PLAN_ID PLAN              NUM_PLAN_DIRECTIVES CPU_METHOD    MGMT_METHOD    ACTIVE_SESS_POOL_MTH         PARALLEL_DEGREE_LIMIT_MTH         QUEUEING_MTH    SUB_PLAN    COMMENTS    STATUS    MANDATORY    

__________ ______________ ______________________ _____________ ______________ ____________________________ _________________________________ _______________ ___________ ___________ _________ ____________ 

     79833 MY_PDB_PLAN                         2 EMPHASIS      EMPHASIS       ACTIVE_SESS_POOL_ABSOLUTE    PARALLEL_DEGREE_LIMIT_ABSOLUTE    FIFO_TIMEOUT    NO                                NO           


SQL> 


コンシューマ・グループRESTRICT_RUNAWAYの存在を確認します。

select * from dba_rsrc_consumer_groups where consumer_group = 'RESTRICT_RUNAWAY';

SQL> select * from dba_rsrc_consumer_groups where consumer_group = 'RESTRICT_RUNAWAY';


   CONSUMER_GROUP_ID CONSUMER_GROUP      CPU_METHOD     MGMT_METHOD    INTERNAL_USE    COMMENTS    CATEGORY    STATUS    MANDATORY    

____________________ ___________________ ______________ ______________ _______________ ___________ ___________ _________ ____________ 

               79834 RESTRICT_RUNAWAY    ROUND-ROBIN    ROUND-ROBIN    NO                          OTHER                 NO           


SQL> 


設定されているプラン・ディレクティブを確認します。

select plan, group_or_subplan, switch_group, switch_for_call, switch_time_in_call, switch_elapsed_time
from dba_rsrc_plan_directives
where plan = 'MY_PDB_PLAN' and group_or_subplan = 'RESTRICT_RUNAWAY';

SQL> select plan, group_or_subplan, switch_group, switch_for_call, switch_time_in_call, switch_elapsed_time

  2  from dba_rsrc_plan_directives

  3* where plan = 'MY_PDB_PLAN' and group_or_subplan = 'RESTRICT_RUNAWAY';


PLAN           GROUP_OR_SUBPLAN    SWITCH_GROUP    SWITCH_FOR_CALL       SWITCH_TIME_IN_CALL    SWITCH_ELAPSED_TIME 

______________ ___________________ _______________ __________________ ______________________ ______________________ 

MY_PDB_PLAN    RESTRICT_RUNAWAY    CANCEL_SQL      TRUE                                   10                     20 


SQL> 


以上で、リソース・マネージャ・プランの構成は完了です。

リソース・マネージャ・プランの有効化し、確認します。

alter system set resource_manager_plan = 'MY_PDB_PLAN' scope=both;
select name, is_top_plan, cpu_managed from v$rsrc_plan where is_top_plan = 'TRUE';

SQL> alter system set resource_manager_plan = 'MY_PDB_PLAN' scope=both;


Systemが変更されました。


SQL> select name, is_top_plan, cpu_managed from v$rsrc_plan where is_top_plan = 'TRUE';


NAME           IS_TOP_PLAN    CPU_MANAGED    

______________ ______________ ______________ 

MY_PDB_PLAN    TRUE           ON             


SQL> 



動作確認



データベースにEntra IDでユーザー認証して接続します。時間が経っている場合、az account get-access-tokenコマンドを実行してトークンを更新します。

az account get-access-token --scope "アプリケーションIDのURI/session:scope:connect" --query accessToken -o tsv > token.txt

データベースに接続します。

sql /@orclpdb1_tls_oauth

% sql /@orclpdb1_tls_oauth


SQLcl: 木 3月 26 18:28:50 2026のリリース25.4 Production


Copyright (c) 1982, 2026, Oracle.  All rights reserved.


接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> 


現在セッションに適用されているリソース・コンシューマー・グループを確認します。

select resource_consumer_group from v$session where audsid = sys_context('USERENV','SESSIONID');

SQL> select resource_consumer_group from v$session where audsid = sys_context('USERENV','SESSIONID');


RESOURCE_CONSUMER_GROUP    

__________________________ 

OTHER_GROUPS               


SQL> 


リソース・コンシューマー・グループがOTHER_GROUPSなので、高負荷SQLの中断が実施されません。リソース・コンシューマー・グループをRESTRICT_RUNAWAYに切り替えます。
declare
  old_group varchar2(30);
begin
  dbms_session.switch_current_consumer_group('RESTRICT_RUNAWAY', old_group, FALSE);
end;
/

SQL> declare

  2    old_group varchar2(30);

  3  begin

  4    dbms_session.switch_current_consumer_group('RESTRICT_RUNAWAY', old_group, FALSE);

  5  end;

  6* /


PL/SQLプロシージャが正常に完了しました。


SQL> select resource_consumer_group from v$session where audsid = sys_context('USERENV','SESSIONID');


RESOURCE_CONSUMER_GROUP    

__________________________ 

RESTRICT_RUNAWAY           


SQL> 


時間表示を有効にして、時間のかかるSQLを実行します。

set time on timing on
select count(*) from all_objects, all_objects;

今回、リソース・マネージャでは経過時間の上限を20秒としています。20秒経過すると、以下のエラーが発生し、SQLの実行が中断されたことが確認できます。

ORA-00040: active time limit exceeded - call aborted

SQL> set time on timing on

18:33:44 SQL> select count(*) from all_objects, all_objects;


次のコマンドの開始中にエラーが発生しました : 行 1 -

select count(*) from all_objects, all_objects

エラー・レポート -

ORA-00040: active time limit exceeded - call aborted


https://docs.oracle.com/error-help/db/ora-00040/


More Details :

https://docs.oracle.com/error-help/db/ora-00040/

経過時間: 00:00:11.710

18:34:01 SQL> 


ユーザーMCPUSERで接続した時は、常にリソース・コンシューマー・グループRESTRICT_RUNAWAYが割り当たるようにします。

ORCLPDB1にユーザーSYSで接続し、以下のスクリプトを実行します。
begin
  dbms_resource_manager.clear_pending_area();
  dbms_resource_manager.create_pending_area();

  /*
   * assosiate RESTRICT_RUNAWAY with MCPUSER
   */
  dbms_resource_manager.set_consumer_group_mapping(
    attribute      => DBMS_RESOURCE_MANAGER.ORACLE_USER,
    value          => 'MCPUSER',
    consumer_group => 'RESTRICT_RUNAWAY');

  dbms_resource_manager.validate_pending_area();
  dbms_resource_manager.submit_pending_area();
end;
/

SQL> begin

  2    dbms_resource_manager.clear_pending_area();

  3    dbms_resource_manager.create_pending_area();

  4  

  5    /*

  6     * assosiate RESTRICT_RUNAWAY with MCPUSER

  7     */

  8    dbms_resource_manager.set_consumer_group_mapping(

  9      attribute      => DBMS_RESOURCE_MANAGER.ORACLE_USER,

 10      value          => 'MCPUSER',

 11      consumer_group => 'RESTRICT_RUNAWAY');

 12  

 13    dbms_resource_manager.validate_pending_area();

 14    dbms_resource_manager.submit_pending_area();

 15  end;

 16* /


PL/SQLプロシージャが正常に完了しました。


SQL> 


コンシューマー・グループのデータベース・ユーザーへのマッピングを確認します。

select attribute, value, consumer_group from dba_rsrc_group_mappings
where consumer_group = 'RESTRICT_RUNAWAY';

SQL> select attribute, value, consumer_group from dba_rsrc_group_mappings

  2* where consumer_group = 'RESTRICT_RUNAWAY';


ATTRIBUTE      VALUE      CONSUMER_GROUP      

______________ __________ ___________________ 

ORACLE_USER    MCPUSER    RESTRICT_RUNAWAY    


SQL> 


今回の設定ではマッピングは1つだけなので影響はありませんが、デフォルトのマッピングの優先度を確認します。ORACLE_USERは7番目です。

select * from dba_rsrc_mapping_priority;

SQL> select * from dba_rsrc_mapping_priority;


ATTRIBUTE                   PRIORITY STATUS    

________________________ ___________ _________ 

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           


11行が選択されました。 


SQL> 


以上でユーザーMCPUSERで接続した時に、リソース・コンシューマー・グループRESTRICT_RUNAWAYが割り当たるようになりました。

データベースへ接続し、セッションに割り当てられたリソース・コンシューマー・グループがRESTRICT_RUNAWAYであることを確認します。

% sql /@orclpdb1_tls_oauth  


SQLcl: 木 3月 26 18:42:38 2026のリリース25.4 Production


Copyright (c) 1982, 2026, Oracle.  All rights reserved.


接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> select resource_consumer_group from v$session where audsid = sys_context('USERENV','SESSIONID');


RESOURCE_CONSUMER_GROUP    

__________________________ 

RESTRICT_RUNAWAY           


SQL> 


MCP Inspectorを起動します。

npx -y @modelcontextprotocol/inspector

SQLclのMCPサーバーのツールrun_sqlから実行時間の長いSQLを実行し、リソース・マネージャによりSQLの処理が中断されることを確認します。

リソース・マネージャーによる切断は経過時間が20秒で発生します。MCP InspectorのConfigurationRequest Timeoutの値が20秒以下(20000以下)の場合は、リソース・マネージャーによるSELECT 文のキャンセルより先に、MCP InspectorがRequest timeoutとして検知します。そのため、この値を20000以上に変更しておきます。


以上で動作確認は完了です。


設定のクリーンアップ



PDBにユーザーSYSで接続し、リソース・マネージャーの設定を解除します。

alter system set resource_manager_plan = '' scope=both;

SQL> alter system set resource_manager_plan = '' scope=both;


Systemが変更されました。


SQL>


ユーザーMCPUSERへのリソース・コンシューマー・グループのマッピングを解除します。解除後、マッピングが解除されていることを確認します。
begin
  dbms_resource_manager.clear_pending_area();
  dbms_resource_manager.create_pending_area();

  dbms_resource_manager.set_consumer_group_mapping(
    attribute      => DBMS_RESOURCE_MANAGER.ORACLE_USER,
    value          => 'MCPUSER',
    consumer_group => '');

  dbms_resource_manager.validate_pending_area();
  dbms_resource_manager.submit_pending_area();
end;
/
select attribute, value, consumer_group from dba_rsrc_group_mappings
where attribute = 'ORACLE_USER';

SQL> begin

  2    dbms_resource_manager.clear_pending_area();

  3    dbms_resource_manager.create_pending_area();

  4  

  5    dbms_resource_manager.set_consumer_group_mapping(

  6      attribute      => DBMS_RESOURCE_MANAGER.ORACLE_USER,

  7      value          => 'MCPUSER',

  8      consumer_group => '');

  9  

 10    dbms_resource_manager.validate_pending_area();

 11    dbms_resource_manager.submit_pending_area();

 12  end;

 13* /


PL/SQLプロシージャが正常に完了しました。


SQL> select attribute, value, consumer_group from dba_rsrc_group_mappings

  2* where attribute = 'ORACLE_USER';


ATTRIBUTE      VALUE     CONSUMER_GROUP    

______________ _________ _________________ 

ORACLE_USER    SYS       SYS_GROUP         

ORACLE_USER    SYSTEM    SYS_GROUP         


SQL> 


リソース・コンシューマー・グループRESTRICT_RUNAWAYおよびリソース・マネージャー・プランMY_PDB_PLANを削除します。以下のスクリプトを実行します。

SQL> @ delete_RESTICT_RUNAWAY.sql 

delete plan directive of MY_PDB_PLAN and RESTRICT_RUNAWAY

delete resource manager plan MY_PDB_PLAN

delete consumer_group RESTRICT_RUNAWAY

pending area submitted successfully.



PL/SQLプロシージャが正常に完了しました。


SQL> 


CDBに接続して、resource_manager_planの設定を消去します。

alter system set resource_manager_plan = '' scope=both;

% sql sys@localhost/orcl as sysdba



SQLcl: 木 3月 26 19:13:01 2026のリリース25.4 Production


Copyright (c) 1982, 2026, Oracle.  All rights reserved.


パスワード (**********?) ******

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> alter system set resource_manager_plan = '' scope=both;


Systemが変更されました。


SQL> exit

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0から切断されました

% 


今回の記事は以上になります。