2025年9月2日火曜日

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

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
 

orcl19c % sql sys@localhost/orcl as sysdba 



SQLcl: 火 9月 02 12:58:02 2025のリリース25.2 Production


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


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

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> 


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

show parameter resource_manager_plan

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

SQL> show parameter resource_manager_plan

NAME                  TYPE   VALUE 

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

resource_manager_plan string       

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> exit

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0から切断されました

orcl19c %  


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


PDBの構成



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

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

sql sys@localhost/orclpdb1 as sysdba

orcl19c % sql sys@localhost/orclpdb1 as sysdba



SQLcl: 火 9月 02 13:10:20 2025のリリース25.2 Production


Copyright (c) 1982, 2025, 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、リソース・マネージャ・プランとしてMCPUSER_PLANを作成し、経過時間の上限を20秒CPU時間の上限を10秒として、SQLを中断するプラン・ディレクティブを作成します。

作成したコンシューマ・グループをMCPサーバーの接続ユーザーMCPUSERに紐づけます。


SQL> begin

  2    dbms_resource_manager.create_pending_area();

  3    /* コンシューマー・グループRESTRICT_RUNAWAYを作成する。 */

  4    dbms_resource_manager.create_consumer_group(consumer_group => 'RESTRICT_RUNAWAY');

  5    /* リソース・マネージャ・プランMCPUSER_PLANを作成する。 */

  6    dbms_resource_manager.create_plan(plan => 'MCPUSER_PLAN');

  7    /*

  8     * プラン・ディレクティブを作成する。

  9     * 経過時間は上限20秒、CPU時間は上限10秒とする。

 10     */

 11    dbms_resource_manager.create_plan_directive(

 12      plan                => 'MCPUSER_PLAN',

 13      group_or_subplan    => 'RESTRICT_RUNAWAY',

 14      switch_group        => 'CANCEL_SQL',

 15      switch_for_call     => TRUE,

 16      switch_elapsed_time => 20, -- 経過時間

 17      switch_time         => 10  -- CPU時間

 18    );

 19    /* デフォルトのプラン・ディレクティブを作成する。 */

 20    dbms_resource_manager.create_plan_directive(

 21      plan                => 'MCPUSER_PLAN',

 22      group_or_subplan    => 'OTHER_GROUPS');

 23    /* 操作終了 */  

 24    dbms_resource_manager.validate_pending_area();

 25    dbms_resource_manager.submit_pending_area();

 26  end;

 27* /


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


SQL> /*

  2   * 作成したコンシューマ・グループをユーザーMCPUSERに紐づける。

  3*  */

SQL> begin

  2    dbms_resource_manager.create_pending_area();

  3    /* コンシューマ・グループをユーザーMCPUSERに適用する。 */

  4    dbms_resource_manager.set_consumer_group_mapping(

  5      attribute      => DBMS_RESOURCE_MANAGER.ORACLE_USER,

  6      value          => 'MCPUSER',

  7      consumer_group => 'RESTRICT_RUNAWAY');

  8    /* 操作終了 */

  9    dbms_resource_manager.validate_pending_area();

 10    dbms_resource_manager.submit_pending_area();

 11  end;

 12* /


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


SQL> 


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

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

select * from dba_rsrc_plans where plan = 'MCPUSER_PLAN';

SQL> select * from dba_rsrc_plans where plan = 'MCPUSER_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    

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

     74433 MCPUSER_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    

____________________ ___________________ ______________ ______________ _______________ ___________ ___________ _________ ____________ 

               74434 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 = 'MCPUSER_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 = 'MCPUSER_PLAN' and group_or_subplan = 'RESTRICT_RUNAWAY';


PLAN            GROUP_OR_SUBPLAN    SWITCH_GROUP    SWITCH_FOR_CALL       SWITCH_TIME_IN_CALL    SWITCH_ELAPSED_TIME 

_______________ ___________________ _______________ __________________ ______________________ ______________________ 

MCPUSER_PLAN    RESTRICT_RUNAWAY    CANCEL_SQL      TRUE                                   10                     20 


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> 


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

残りの作業はリソース・マネージャ・プランの有効化です。以下のコマンドを実行しますが、一旦、動作確認を行うために設定を保留します。

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


動作確認



データベースにEntra IDでユーザー認証して接続します。

sql /@orclpdb1_tls_oauth

orcl19c % sql /@orclpdb1_tls_oauth



SQLcl: 火 9月 02 14:11:52 2025のリリース25.2 Production


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


接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL>


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

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

今回、リソース・マネージャでは経過時間の上限を20秒としています。まだ、リソース・マネージャ・プランを設定していなので、20秒を過ぎても処理は継続します。CTRL+Cを入力して処理を中断します。

SQL> set time on timing on

15:50:23 SQL> select count(*) from all_objects, all_objects;

^C15:51:18 SQL> 


PDBにSYSで接続し、リソース・マネージャ・プランとしてMCPUSER_PLANを設定します。

orcl19c % sql sys@localhost/orclpdb1 as sysdba



SQLcl: 火 9月 02 15:51:52 2025のリリース25.2 Production


Copyright (c) 1982, 2025, 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 = 'MCPUSER_PLAN' scope=both;


Systemが変更されました。


SQL> exit

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0から切断されました

orcl19c % 


データベースにEntra IDでユーザー認証して接続して、リソース・マネージャによりSQLの実行が20秒で切断されることを確認します。

以下のエラーが発生し、SQLの実行が中断されたことが確認できます。

ORA-00040: アクティブな時間制限を超えました - コールは異常終了しました

orcl19c % sql /@orclpdb1_tls_oauth



SQLcl: 火 9月 02 15:56:29 2025のリリース25.2 Production


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


接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0


SQL> set time on timing on

15:56:45 SQL> select count(*) from all_objects, all_objects;


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

select count(*) from all_objects, all_objects

エラー・レポート -

ORA-00040: アクティブな時間制限を超えました - コールは異常終了しました


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


More Details :

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

経過時間: 00:00:11.873

15:56:58 SQL> exit

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.19.0.0.0から切断されました

orcl19c % 


MCP Inspectorを起動します。

npx -y @modelcontextprotocol/inspector

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

リソース・マネージャの設定通り、SQLの実行が20秒ほど経過したときにエラーが返されました。ORA-40がそのまま返されず、MCP error -32001: Request timed outとなっています。


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


設定のクリーンアップ



PDBに接続して、以下のスクリプトを実行します。
alter system set resource_manager_plan = '' scope=both;
begin
  dbms_resource_manager.create_pending_area();
  dbms_resource_manager.delete_plan(
    plan => 'MCPUSER_PLAN');
  dbms_resource_manager.delete_consumer_group(consumer_group => 'RESTRICT_RUNAWAY');
  dbms_resource_manager.validate_pending_area();
  dbms_resource_manager.submit_pending_area();
end;
/
CDBに接続して、resource_manager_planの設定を消去します。

alter system set resource_manager_plan = '' scope=both;

orcl19c % sql sys@localhost/orcl as sysdba



SQLcl: 火 9月 02 16:12:07 2025のリリース25.2 Production


Copyright (c) 1982, 2025, 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から切断されました

orcl19c % 



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