DBMS_APPLICATION_INFOは、実行中のPL/SQLやアプリケーション処理の「いま何をやっているか」をデータベース側へ明示するための標準パッケージです。V$SESSIONやAWR、ASHの画面にモジュール名やアクション名、長時間処理の進捗を出力できるため、性能分析や運用監視で非常に有効です。ここでは基本の使い方から、長時間処理の進捗表示、バッチでの設計パターン、計測ツールとの併用までを解説します。
基本:モジュール名とアクション名を設定する
モジュール名とアクション名はDBMS_APPLICATION_INFO.SET_MODULEで設定します。処理ブロックの入口で設定し、完了時にクリアするのが基本です。ユーザー側から見えるのはV$SESSIONのMODULE列とACTION列で、誰がどの機能を実行しているかを瞬時に把握できます。
BEGIN
DBMS_APPLICATION_INFO.SET_MODULE(
module_name => 'MONTHLY_BILLING',
action_name => 'STEP1_LOAD');
-- ここでSTEP1の処理
DBMS_APPLICATION_INFO.SET_ACTION('STEP2_AGGREGATE');
-- ここでSTEP2の処理
DBMS_APPLICATION_INFO.SET_MODULE(NULL, NULL); -- 終了時にクリア
END;
/
アクションだけを切り替えたい場合はSET_ACTIONを逐次呼び出します。例外で中断する可能性がある処理では、例外節で必ずNULLへ戻すようにしておくと監視画面に残骸が残りません。
V$SESSIONから現在の状況を確認する
監視者はセッション識別子やログインユーザーでV$SESSIONを引き、MODULEとACTIONで状況を把握できます。トラブル時に「どのステップで止まっているか」を即座に特定できます。
SELECT sid, serial#, module, action, status, event
FROM v$session
WHERE username = 'APP_USER'
ORDER BY logon_time DESC;
長時間処理の進捗を出す(SET_SESSION_LONGOPS)
数分から数時間に渡る処理は、DBMS_APPLICATION_INFO.SET_SESSION_LONGOPSを使って進捗バーのような情報をV$SESSION_LONGOPSへ出力します。トータル作業量と現在の進捗値を段階的に報告すると、残り時間の見積りが監視画面で可視化されます。
DECLARE
r BINARY_INTEGER;
sofar NUMBER := 0;
total NUMBER := 100000; -- 総レコード数などの目標値
BEGIN
DBMS_APPLICATION_INFO.SET_MODULE('MONTHLY_BILLING', 'STEP3_EXPORT');
DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS_NOHINT(r, NULL, NULL, 'Export rows', 0, sofar, total, 'rows');
FOR i IN 1..total LOOP
-- 明細1件の処理
sofar := sofar + 1;
IF MOD(sofar, 1000) = 0 THEN
DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS(r, NULL, NULL, 'Export rows', 0, sofar, total, 'rows');
END IF;
END LOOP;
DBMS_APPLICATION_INFO.SET_MODULE(NULL, NULL);
END;
/
監視側はV$SESSION_LONGOPSを参照すれば、今の進捗率や経過時間、完了予測を確認できます。
SELECT sl.opname, sl.sofar, sl.totalwork, sl.units,
ROUND(sl.sofar*100/NULLIF(sl.totalwork,0),1) AS pct
FROM v$session_longops sl
WHERE sl.username = 'APP_USER'
AND sl.totalwork > 0
ORDER BY sl.start_time DESC;
バッチ処理でのテンプレート化
実務ではモジュールとアクション、長時間処理の更新、完了後のクリアを毎回正しく書くのが肝心です。共通ヘルパーを用意すると漏れが減ります。
CREATE OR REPLACE PACKAGE app_instr AS
PROCEDURE enter(p_module VARCHAR2, p_action VARCHAR2 := NULL);
PROCEDURE action(p_action VARCHAR2);
PROCEDURE leave;
PROCEDURE longops_init(p_opname VARCHAR2, p_total NUMBER, p_units VARCHAR2 := 'rows');
PROCEDURE longops_step(p_inc NUMBER := 1);
END;
/
CREATE OR REPLACE PACKAGE BODY app_instr AS
g_r BINARY_INTEGER;
g_total NUMBER;
g_sofar NUMBER;
PROCEDURE enter(p_module VARCHAR2, p_action VARCHAR2) IS
BEGIN
DBMS_APPLICATION_INFO.SET_MODULE(p_module, p_action);
END;
PROCEDURE action(p_action VARCHAR2) IS
BEGIN
DBMS_APPLICATION_INFO.SET_ACTION(p_action);
END;
PROCEDURE leave IS
BEGIN
DBMS_APPLICATION_INFO.SET_MODULE(NULL, NULL);
END;
PROCEDURE longops_init(p_opname VARCHAR2, p_total NUMBER, p_units VARCHAR2) IS
BEGIN
g_total := p_total; g_sofar := 0;
DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS_NOHINT(g_r, NULL, NULL, p_opname, 0, 0, g_total, p_units);
END;
PROCEDURE longops_step(p_inc NUMBER) IS
BEGIN
g_sofar := g_sofar + NVL(p_inc,1);
DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS(g_r, NULL, NULL, NULL, 0, g_sofar, g_total, NULL);
END;
END;
/
テンプレート化したら、業務処理側では簡潔に計器を埋め込めます。
BEGIN
app_instr.enter('ORDER_IMPORT','READ_FILE');
-- 入力読み込み
app_instr.action('VALIDATE_ROWS');
-- バリデーション
app_instr.longops_init('Import rows', 500000, 'rows');
FOR i IN 1..500000 LOOP
-- 1件処理
IF MOD(i, 2000) = 0 THEN app_instr.longops_step(2000); END IF;
END LOOP;
app_instr.leave;
EXCEPTION
WHEN OTHERS THEN
app_instr.leave; -- 例外時も必ずクリア
RAISE;
END;
/
DBMS_PROFILERやAWRとの併用
モジュール名とアクション名はAWRやASHのレポートにも記録されます。期間全体の遅延を俯瞰するにはAWRを参照し、行粒度でのホットスポット特定にはDBMS_PROFILERを使い、どのモジュールのどのアクションが重いかを二軸で見ると原因切り分けが速くなります。アプリケーションログの相関IDをMODULEやACTIONに含める運用にすると、監視結果とアプリログを突き合わせやすくなります。
命名規約と運用上の注意
MODULEにはシステム名や機能ブロックを短く入れ、ACTIONには現在のステップやフェーズを時系列で分かる語で入れると読み取りやすくなります。例外の握り潰しでACTIONが古いまま残ると誤認の原因となるため、必ず例外節でleave相当のクリア処理を呼びます。短時間の微細な処理まで頻繁にSET_ACTIONを呼ぶとオーバーヘッドとラッチ競合のノイズになるため、数秒以上のまとまりで更新する方が安定します。長時間処理のSET_SESSION_LONGOPSは全件ごとではなくバッチ単位で更新し、V$SESSION_LONGOPSの行が無制限に増えないよう適度な更新間隔を守ります。
まとめ
DBMS_APPLICATION_INFOは、データベース視点で処理の現在地と進捗を可視化する計器です。SET_MODULEとSET_ACTIONで機能名とステップを掲示し、SET_SESSION_LONGOPSで長時間処理の進捗を報告すれば、監視と障害対応のスピードが向上します。共通ヘルパーで必ず設定とクリアを行う習慣を作り、プロファイラやAWRと組み合わせてボトルネックを客観的に特定する運用へつなげましょう。