「遅いクエリがどのアプリケーション機能から来ているのか判断できない」という場面で役立つのがDBMS_APPLICATION_INFO パッケージです。PL/SQL から実行中のモジュール名・アクション名・クライアント情報を Oracle セッションに設定でき、V$SESSION や AWR レポートでその情報を活用できます。
APM(Application Performance Management)ツールを導入せずとも、DBMS_APPLICATION_INFO を活用することでどの機能のどの処理が負荷を与えているかを特定しやすくなります。
この記事でわかること
- SET_MODULE / SET_ACTION / SET_CLIENT_INFO でセッション情報を設定する方法
- V$SESSION の module / action / client_info でセッションを識別する方法
- AWR がモジュール・アクション単位でパフォーマンスデータを集計する仕組み
- READ_MODULE で現在のモジュール・アクションを読み取る方法
- SYS_CONTEXT(‘USERENV’, …) でセッション情報を参照する方法
SET_MODULE・SET_ACTION でセッション情報を設定する
モジュール(module)はアプリケーション名に相当し、アクション(action)はその機能名・処理名に相当します。処理の開始時に設定し、終了時にクリアするパターンで使います。
SET_MODULE と SET_ACTION の基本的な使い方
-- プロシージャ内でモジュール・アクションを設定する例
CREATE OR REPLACE PROCEDURE process_monthly_sales AS
v_module VARCHAR2(48); -- 保存用(元の値を退避)
v_action VARCHAR2(32);
BEGIN
-- 現在の設定を退避する(呼び出し元のコンテキストを壊さないために)
DBMS_APPLICATION_INFO.READ_MODULE(v_module, v_action);
-- モジュールとアクションを設定する
-- module: アプリケーション名(最大 48 バイト)
-- action: 機能名・処理名(最大 32 バイト)
DBMS_APPLICATION_INFO.SET_MODULE(
module_name => 'BATCH_SALES',
action_name => 'AGGREGATE_MONTHLY'
);
-- 実際の処理
-- ... 集計処理 ...
DBMS_APPLICATION_INFO.SET_ACTION('INSERT_SUMMARY');
-- ... サマリ INSERT 処理 ...
DBMS_APPLICATION_INFO.SET_ACTION('SEND_REPORT');
-- ... レポート送信 ...
-- 処理終了後にクリアする(元の値に戻す)
DBMS_APPLICATION_INFO.SET_MODULE(v_module, v_action);
EXCEPTION
WHEN OTHERS THEN
DBMS_APPLICATION_INFO.SET_MODULE(v_module, v_action);
RAISE;
END process_monthly_sales;
/
SET_CLIENT_INFO でクライアント固有の情報を設定する
-- client_info はアプリケーション独自の情報(最大 64 バイト)
-- 例: ユーザー ID・テナント ID・リクエスト ID など
BEGIN
DBMS_APPLICATION_INFO.SET_CLIENT_INFO(
client_info => 'USER_ID=12345|TENANT=ACME_CORP'
);
END;
/
-- 設定した情報を確認する
SELECT
SYS_CONTEXT('USERENV', 'MODULE') AS module,
SYS_CONTEXT('USERENV', 'ACTION') AS action,
SYS_CONTEXT('USERENV', 'CLIENT_INFO') AS client_info
FROM DUAL;
V$SESSION で設定情報を確認する
V$SESSION でモジュール・アクション情報を確認する
-- 現在実行中のセッションのモジュール・アクション情報を確認する
SELECT
s.sid,
s.serial#,
s.username,
s.module, -- DBMS_APPLICATION_INFO.SET_MODULE で設定した値
s.action, -- DBMS_APPLICATION_INFO.SET_ACTION で設定した値
s.client_info, -- DBMS_APPLICATION_INFO.SET_CLIENT_INFO で設定した値
s.client_identifier, -- DBMS_SESSION.SET_IDENTIFIER で設定する値
s.status,
s.event,
s.seconds_in_wait
FROM V$SESSION s
WHERE s.type = 'USER'
AND s.module IS NOT NULL -- モジュールが設定されているセッションのみ
ORDER BY s.module, s.action;
-- 特定のモジュールで高負荷になっているセッションを特定する
SELECT
s.sid, s.serial#, s.username,
s.module, s.action,
s.event, s.seconds_in_wait,
s.sql_id
FROM V$SESSION s
WHERE s.module = 'BATCH_SALES'
AND s.status = 'ACTIVE'
ORDER BY s.seconds_in_wait DESC;
AWR によるモジュール・アクション単位のパフォーマンス集計
AWR はモジュール・アクション情報を収集し、どの機能がデータベースリソースを消費しているかを集計します。DBA_HIST_SQLSTAT にモジュール・アクション情報が保存されます。
AWR でモジュール別の SQL パフォーマンスを分析する
-- 直近の AWR スナップショットでモジュール別の実行時間を集計する
SELECT
sql.module,
sql.action,
COUNT(DISTINCT sql.sql_id) AS sql_count,
SUM(sql.executions_delta) AS total_executions,
ROUND(SUM(sql.elapsed_time_delta) / 1e6) AS total_elapsed_sec,
ROUND(SUM(sql.cpu_time_delta) / 1e6) AS total_cpu_sec,
ROUND(SUM(sql.buffer_gets_delta)) AS total_buffer_gets
FROM DBA_HIST_SQLSTAT sql
JOIN DBA_HIST_SNAPSHOT snap
ON sql.snap_id = snap.snap_id
WHERE snap.begin_interval_time >= SYSDATE - 1 -- 過去 24 時間
AND sql.module IS NOT NULL
GROUP BY sql.module, sql.action
ORDER BY total_elapsed_sec DESC
FETCH FIRST 20 ROWS ONLY;
-- モジュール単位の SQL ランキングを確認する(特定モジュールの詳細)
SELECT
sql.sql_id,
sql.action,
sql.executions_delta AS executions,
ROUND(sql.elapsed_time_delta / NULLIF(sql.executions_delta, 0) / 1000) AS avg_ms,
SUBSTR(stext.sql_text, 1, 80) AS sql_head
FROM DBA_HIST_SQLSTAT sql
JOIN DBA_HIST_SQLTEXT stext
ON sql.sql_id = stext.sql_id
JOIN DBA_HIST_SNAPSHOT snap
ON sql.snap_id = snap.snap_id
WHERE snap.begin_interval_time >= SYSDATE - 1
AND sql.module = 'BATCH_SALES'
AND sql.executions_delta > 0
ORDER BY avg_ms DESC
FETCH FIRST 10 ROWS ONLY;
READ_MODULE で現在の設定を読み取る
READ_MODULE で現在のモジュール・アクションを確認する
-- 現在設定されているモジュールとアクションを取得する
DECLARE
v_module VARCHAR2(48);
v_action VARCHAR2(32);
BEGIN
DBMS_APPLICATION_INFO.READ_MODULE(
module_name => v_module,
action_name => v_action
);
DBMS_OUTPUT.PUT_LINE('MODULE: ' || NVL(v_module, '(未設定)'));
DBMS_OUTPUT.PUT_LINE('ACTION: ' || NVL(v_action, '(未設定)'));
END;
/
SYS_CONTEXT でセッション情報を参照する
SYS_CONTEXT は SQL から直接セッション情報を参照できる組み込み関数です。WHERE 句やビューの定義に組み込んで行レベルのアクセス制御に活用できます。
SYS_CONTEXT(‘USERENV’, …) の主要なキー一覧
-- よく使う USERENV コンテキスト値を確認する
SELECT
SYS_CONTEXT('USERENV', 'SESSION_USER') AS session_user, -- 現在のユーザー名
SYS_CONTEXT('USERENV', 'DB_NAME') AS db_name, -- データベース名
SYS_CONTEXT('USERENV', 'HOST') AS host, -- クライアントホスト名
SYS_CONTEXT('USERENV', 'IP_ADDRESS') AS ip_address, -- クライアント IP
SYS_CONTEXT('USERENV', 'OS_USER') AS os_user, -- OS のログインユーザー名
SYS_CONTEXT('USERENV', 'MODULE') AS module, -- 設定されたモジュール名
SYS_CONTEXT('USERENV', 'ACTION') AS action, -- 設定されたアクション名
SYS_CONTEXT('USERENV', 'CLIENT_INFO') AS client_info, -- 設定されたクライアント情報
SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') AS client_id, -- DBMS_SESSION.SET_IDENTIFIER で設定
SYS_CONTEXT('USERENV', 'SID') AS sid, -- セッション ID
SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AS current_schema, -- 現在のスキーマ
SYS_CONTEXT('USERENV', 'CON_NAME') AS con_name -- コンテナ名(マルチテナント)
FROM DUAL;
-- SYS_CONTEXT を WHERE 句で使う例(テナント分離)
-- ビュー定義に組み込むことで自動的に絞り込まれる
CREATE OR REPLACE VIEW my_orders AS
SELECT * FROM orders
WHERE tenant_id = SYS_CONTEXT('USERENV', 'CLIENT_INFO');
-- セッションごとに SET_CLIENT_INFO で tenant_id を設定することで行レベル分離を実現
まとめ
- SET_MODULE / SET_ACTION:処理の開始・終了時に設定して V$SESSION・AWR でのトレーサビリティを向上させる
- SET_CLIENT_INFO:ユーザー ID・テナント ID などアプリケーション独自の情報を最大 64 バイト格納できる
- V$SESSION.module / action:どのモジュール・アクションが実行中か、どのセッションが遅いかをリアルタイムに特定できる
- AWR / DBA_HIST_SQLSTAT:モジュール・アクション単位で実行時間・CPU・バッファゲットを集計してボトルネックを特定できる
- SYS_CONTEXT(‘USERENV’, …):SQL から直接セッション情報を参照できる。VIEW や RLS ポリシーに組み込んで行レベルセキュリティに活用できる
AWR を使ったパフォーマンス分析は AWR・ASH完全ガイドを参照してください。待機イベントとセッション監視は 待機イベント完全ガイドも参照してください。