大規模なPL/SQLバッチが「動いているのか止まっているのか分からない」「重いSQLがどの機能のどの処理から来たのか追跡できない」「夜間ジョブの進捗を可視化したい」——こんな運用課題を追加コストゼロで解決できるのがDBMS_APPLICATION_INFOパッケージです。
このパッケージは「現在実行中の処理の意味のある名前をV$SESSIONやV$SESSION_LONGOPSに書き込む」シンプルな機能ですが、AWR/ASHレポートでモジュール別集計ができるため、「どの機能が一番DB負荷をかけているか」「どの処理が遅いか」をAPMツールなしで可視化できる強力な仕組みです。
ただし「とりあえずSET_MODULEを呼ぶ」だけの素朴な使い方では本来の価値の半分も引き出せません。ラッパーパッケージで例外時クリーンアップ、SET_SESSION_LONGOPSで進捗バー出力、CLIENT_IDENTIFIERで分散トレース相関ID、JDBCのEnd-to-End Metricsで自動連携といった実戦テクニックが必要です。
この記事ではDBMS_APPLICATION_INFOを運用監視の武器に変える実戦ガイドとして、ラッパー設計・進捗バー実装・AWR/ASH分析・分散トレース・JDBC連携・監視SQLクエリ集・アンチパターン6選・FAQまで2026年版で解説します。
この記事でわかること
- SET_MODULE/SET_ACTION/SET_CLIENT_INFO/SET_CLIENT_IDENTIFIERの使い分け
- 例外時もコンテキストをクリアする安全なラッパーパッケージ設計
- SET_SESSION_LONGOPSで長時間処理の進捗バーを出す実装
- V$SESSIONからリアルタイムに「いま何をしているか」を見るクエリ
- AWR/ASHレポートでモジュール別にDB負荷を集計する活用法
- CLIENT_IDENTIFIERで分散トレース風の相関IDを実装する手法
- Java/JDBCのsetEndToEndMetricsで自動連携する設定
- 監視・障害対応に使える実用クエリ7種
- 本番で踏むアンチパターン6選
30秒でわかるDBMS_APPLICATION_INFO活用の結論
忙しい読者向けの結論先出しです。
| 結論 | 理由・効果 |
|---|---|
| ① 機能名はMODULE、処理名はACTION | V$SESSION・AWRで集計単位として使われる |
| ② 例外時もクリアするラッパー必須 | 監視画面に古い情報が残ると別障害と誤認される |
| ③ 長時間処理はSET_SESSION_LONGOPSで進捗バー | 残り時間を監視画面で可視化できる |
| ④ AWR/ASHはモジュール別にDB負荷を集計可能 | 「どの機能が遅いか」がレポートで一目瞭然 |
| ⑤ CLIENT_IDENTIFIERで分散トレース相関ID | WebアクセスログとDBログを紐付けて追跡可能 |
| ⑥ JDBCのsetEndToEndMetricsで自動連携 | JavaコードからPL/SQLに渡す手間を省ける |
| ⑦ オーバーヘッドはほぼゼロ本番常時ON可能 | セッション内のメタデータ更新だけなので無料 |
4つのAPIと役割|どれをいつ使うか
DBMS_APPLICATION_INFOには4つの設定系APIがあり、それぞれ役割と保存先カラムが異なります。基本構文と機能網羅はDBMS_APPLICATION_INFO完全ガイドを参照してください。本記事では用途別の使い分けに絞ります。
SET_MODULE(module_name, action_name)|機能名と処理名
「どのアプリ機能か」を表すMODULEと、「その中のどのステップか」を表すACTIONを一度に設定。V$SESSIONのMODULE列・ACTION列に反映され、AWR/ASHの集計キーになります。処理の入口で必ず呼ぶのが基本パターン。
SET_ACTION(action_name)|ステップ切り替え
同じMODULE内でACTIONだけ切り替えるときに使います。バッチ処理の「STEP1抽出→STEP2変換→STEP3ロード」のように段階を進めるたびに呼び出すと、V$SESSIONのACTION列が逐次更新され、リアルタイム監視で「今STEP3にいる」と判別できます。
SET_CLIENT_INFO(client_info)|任意の補足情報
MODULE/ACTIONとは別に、処理対象のIDや具体的な内容を入れたいときに使います。たとえば「ORDER_ID=12345」「BATCH_DATE=20260425」など。V$SESSIONのCLIENT_INFO列に反映されますが、AWR集計の対象外なので「集計したい情報」はACTIONに、「個別レコード識別」はCLIENT_INFOに、と使い分けます。
SET_CLIENT_IDENTIFIER(client_id)|エンドユーザー識別子
「実際にこの処理を要求したエンドユーザーは誰か」を識別する用途。V$SESSIONのCLIENT_IDENTIFIER列に反映され、監査・分散トレース・マルチテナントの集計などに活用します。WebアプリならログインユーザーIDやセッショントークンを設定。分散トレースの相関IDとして使うのが現代的な活用法です。
CREATE OR REPLACE PROCEDURE process_order(
p_order_id IN NUMBER,
p_user_id IN NUMBER
) AS
BEGIN
-- ① 機能名と最初のステップを設定
DBMS_APPLICATION_INFO.SET_MODULE(
module_name => 'OrderService',
action_name => 'validate'
);
-- ② エンドユーザーを識別
DBMS_APPLICATION_INFO.SET_CLIENT_IDENTIFIER(
client_id => 'user_' || p_user_id
);
-- ③ 処理対象の具体情報
DBMS_APPLICATION_INFO.SET_CLIENT_INFO(
client_info => 'ORDER_ID=' || p_order_id
);
pkg_validator.run(p_order_id);
-- ④ ステップ切り替え
DBMS_APPLICATION_INFO.SET_ACTION('persist');
pkg_repo.save(p_order_id);
DBMS_APPLICATION_INFO.SET_ACTION('notify');
pkg_notify.send(p_order_id);
-- ⑤ 終了時にクリア(重要!)
DBMS_APPLICATION_INFO.SET_MODULE(NULL, NULL);
DBMS_APPLICATION_INFO.SET_CLIENT_INFO(NULL);
-- CLIENT_IDENTIFIERは継続セッションなら次の処理でも使える
END;
/
ラッパーパッケージ設計|例外時もコンテキストを安全にクリア
「SET_MODULEを呼んだあとに例外発生→クリアされず監視画面に古い情報が残ったまま」というのが現場でよくある事故です。これを防ぐにはラッパーパッケージで元の値を退避→処理→必ず復元、というパターンを徹底します。
CREATE OR REPLACE PACKAGE pkg_app_info AS
-- スコープに入る(前のコンテキストを退避し新しい値を設定)
PROCEDURE enter(p_module VARCHAR2, p_action VARCHAR2);
-- スコープから出る(前のコンテキストへ復元)
PROCEDURE leave;
-- ステップ切り替え(actionだけ更新)
PROCEDURE step(p_action VARCHAR2);
END pkg_app_info;
/
CREATE OR REPLACE PACKAGE BODY pkg_app_info AS
TYPE t_ctx IS RECORD(module VARCHAR2(48), action VARCHAR2(32));
TYPE t_stack IS TABLE OF t_ctx INDEX BY PLS_INTEGER;
g_stack t_stack;
PROCEDURE enter(p_module VARCHAR2, p_action VARCHAR2) AS
v_idx PLS_INTEGER := NVL(g_stack.LAST, 0) + 1;
v_cur t_ctx;
BEGIN
-- 現在のコンテキストを退避(スタックにpush)
DBMS_APPLICATION_INFO.READ_MODULE(v_cur.module, v_cur.action);
g_stack(v_idx) := v_cur;
-- 新しいコンテキストを設定
DBMS_APPLICATION_INFO.SET_MODULE(p_module, p_action);
END;
PROCEDURE leave AS
v_idx PLS_INTEGER := g_stack.LAST;
v_prev t_ctx;
BEGIN
IF v_idx IS NULL THEN
DBMS_APPLICATION_INFO.SET_MODULE(NULL, NULL);
ELSE
v_prev := g_stack(v_idx);
g_stack.DELETE(v_idx);
DBMS_APPLICATION_INFO.SET_MODULE(v_prev.module, v_prev.action);
END IF;
END;
PROCEDURE step(p_action VARCHAR2) AS
BEGIN
DBMS_APPLICATION_INFO.SET_ACTION(p_action);
END;
END pkg_app_info;
/
-- 利用例:例外時もleaveが必ず呼ばれる
CREATE OR REPLACE PROCEDURE main_batch AS
BEGIN
pkg_app_info.enter('BillingBatch', 'load');
BEGIN
pkg_extract.run;
pkg_app_info.step('transform');
pkg_transform.run;
pkg_app_info.step('insert');
pkg_load.run;
EXCEPTION
WHEN OTHERS THEN
pkg_app_info.leave; -- 必ずクリア
RAISE;
END;
pkg_app_info.leave;
END;
/
スタック式のenter/leaveパターンで、ネストした関数呼び出しでも親のコンテキストが復元されます。「pkg_a.foo→pkg_b.bar→pkg_c.baz」のように深くネストしても、各関数の入口でenter、出口(成功・例外問わず)でleaveを呼ぶだけで監視画面に常に正確な情報が表示されます。コードレビューで「enterとleaveがペアになっているか」を必ずチェックしてください。
SET_SESSION_LONGOPS|長時間処理の進捗バーを表示
夜間バッチや大量データ処理で「いつ終わるのか」を可視化したい場合、SET_SESSION_LONGOPSを使えば進捗バーのような情報をV$SESSION_LONGOPSに出力できます。OEM/Cloud Controlなどの監視ツールはこの情報を読み取って残り時間と進捗率を表示する仕組みになっています。
CREATE OR REPLACE PROCEDURE process_huge_data AS
v_rindex BINARY_INTEGER := DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS_NOHINT;
v_slno BINARY_INTEGER;
v_total NUMBER;
v_processed NUMBER := 0;
BEGIN
-- 全件数を取得(進捗バーの分母)
SELECT COUNT(*) INTO v_total FROM input_data;
pkg_app_info.enter('DataLoad', 'process');
FOR rec IN (SELECT * FROM input_data) LOOP
-- 業務処理
pkg_processor.handle(rec);
v_processed := v_processed + 1;
-- 進捗報告(毎100件ごとに更新)
IF MOD(v_processed, 100) = 0 THEN
DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS(
rindex => v_rindex,
slno => v_slno,
op_name => 'DataLoad processing', -- 操作名
target_desc => 'rows', -- 単位
context => 0,
sofar => v_processed, -- 現在進捗
totalwork => v_total, -- 総量
units => 'rows'
);
END IF;
END LOOP;
pkg_app_info.leave;
END;
/
-- 監視側:V$SESSION_LONGOPSをポーリング
SELECT sid, opname, target,
sofar, totalwork,
ROUND(sofar*100/NULLIF(totalwork,0), 1) AS pct,
elapsed_seconds AS elapsed_sec,
time_remaining AS remaining_sec,
message
FROM v$session_longops
WHERE time_remaining > 0
ORDER BY start_time DESC;
SET_SESSION_LONGOPSの注意点:①SET_SESSION_LONGOPS_NOHINTで初期化したrindexを毎回使う、②あまり頻繁に更新するとオーバーヘッドが見えるので100〜1000件ごとがほどよい更新間隔、③進捗が「6秒以上の処理」と判定されたものだけが残るため短時間の処理は表示されない仕様、④処理終了時にsofar = totalworkにして完了を明示すると監視側でわかりやすい。
AWR/ASHでモジュール別にDB負荷を集計
DBMS_APPLICATION_INFOの真価はAWR/ASHレポートで集計キーとして使えることです。AWRは1時間ごとに性能スナップショットを取り、モジュール別・アクション別にCPU使用率・I/O・待機イベントを集計します。これにより「どの機能が一番DB負荷をかけているか」がレポート1枚で分かるようになります。
-- ① ASHから過去1時間のモジュール別CPU時間TOP10
SELECT
module,
action,
COUNT(*) AS samples,
ROUND(COUNT(*)/(60*60)*10, 2) AS estimated_active_seconds
FROM v$active_session_history
WHERE sample_time > SYSTIMESTAMP - INTERVAL '1' HOUR
AND module IS NOT NULL
GROUP BY module, action
ORDER BY samples DESC
FETCH FIRST 10 ROWS ONLY;
-- ② AWRから日次でモジュール別の負荷ランキング
SELECT
module,
SUM(elapsed_time)/1e6 AS total_sec,
SUM(executions) AS execs,
ROUND(SUM(elapsed_time)/SUM(executions)/1e3, 2) AS avg_ms,
SUM(disk_reads) AS disk_reads,
SUM(buffer_gets) AS buffer_gets
FROM dba_hist_sqlstat ss
JOIN dba_hist_snapshot s ON s.snap_id = ss.snap_id
WHERE s.begin_interval_time > SYSDATE - 1
AND ss.module IS NOT NULL
GROUP BY module
ORDER BY total_sec DESC;
-- ③ 特定モジュール内のアクション別ボトルネック
SELECT
action,
COUNT(*) AS samples,
COUNT(DISTINCT session_id) AS sessions,
COUNT(*) FILTER(WHERE session_state = 'WAITING') AS waiting,
ROUND(SUM(CASE WHEN session_state = 'ON CPU' THEN 1 ELSE 0 END)*100.0
/COUNT(*), 1) AS on_cpu_pct
FROM v$active_session_history
WHERE module = 'BillingBatch'
AND sample_time > SYSTIMESTAMP - INTERVAL '6' HOUR
GROUP BY action
ORDER BY samples DESC;
-- ④ 時系列でモジュールの負荷変動を可視化
SELECT
TO_CHAR(TRUNC(sample_time, 'MI'), 'HH24:MI') AS minute,
module,
COUNT(*) AS samples
FROM v$active_session_history
WHERE sample_time > SYSTIMESTAMP - INTERVAL '1' HOUR
AND module IS NOT NULL
GROUP BY TRUNC(sample_time, 'MI'), module
ORDER BY minute, samples DESC;
AWRレポートの「Top SQL by Module」「Module Statistics」セクションはDBMS_APPLICATION_INFOで設定したMODULE名で集計されています。逆に言えばモジュール名を設定していない処理はすべて「JDBC Thin Client」のような汎用ラベルにまとめられ、「どの機能が問題か」が見えなくなります。リリース前に主要処理のすべてに意味あるモジュール名を設定する習慣を徹底してください。
CLIENT_IDENTIFIERで分散トレース相関ID
マイクロサービスやWebアプリで「ユーザーリクエストAがDBで何をしたか」を追跡するには相関IDが必要です。DBMS_APPLICATION_INFOのSET_CLIENT_IDENTIFIERにリクエストUUID/トレースIDを入れると、V$SESSION・AWR・監査ログでアプリケーションログと突合できます。
-- アプリ層からトレースIDを渡す
CREATE OR REPLACE PROCEDURE api_create_order(
p_trace_id IN VARCHAR2,
p_user_id IN NUMBER,
p_payload IN CLOB
) AS
BEGIN
-- ① 相関IDを設定(W3C Trace ContextやAWS X-Ray IDなど)
DBMS_APPLICATION_INFO.SET_CLIENT_IDENTIFIER(p_trace_id);
DBMS_APPLICATION_INFO.SET_MODULE('OrderAPI', 'create');
-- ② 業務処理
pkg_order_service.create_order(p_user_id, p_payload);
-- ③ クリア
DBMS_APPLICATION_INFO.SET_MODULE(NULL, NULL);
DBMS_APPLICATION_INFO.SET_CLIENT_IDENTIFIER(NULL);
END;
/
-- 監視側:特定の相関IDのトラブルシュート
SELECT s.sid, s.serial#, s.module, s.action,
q.sql_id, q.sql_text
FROM v$session s
LEFT JOIN v$sqlarea q ON q.sql_id = s.sql_id
WHERE s.client_identifier = '550e8400-e29b-41d4-a716-446655440000'
ORDER BY s.last_call_et DESC;
-- ASHで該当リクエストの全SQLとボトルネックを抽出
SELECT sample_time, sql_id, event,
module, action, blocking_session
FROM v$active_session_history
WHERE client_id = '550e8400-e29b-41d4-a716-446655440000'
ORDER BY sample_time;
OpenTelemetry/AWS X-Ray/DatadogなどのトレースIDをCLIENT_IDENTIFIERに渡すと、アプリ層のトレースとDB層の動作が完全に紐付き、「このユーザーリクエストがDBでORA-XXX例外で失敗した」「Web側で1秒のうちDBが800ms費やしていた」のような原因切り分けが可能になります。本格的な分散トレース基盤を持っていない環境でも相関IDを通すだけで観測性が桁違いに向上します。
JDBC連携|setEndToEndMetricsで自動連携
JavaアプリケーションからOracleに接続する場合、OracleConnection.setEndToEndMetricsを使うとPL/SQL側でDBMS_APPLICATION_INFOを呼ばなくてもモジュール名/アクション名/クライアントIDをセッションに自動設定できます。Spring等のフレームワークではAOPでさらに自動化することも可能です。
import oracle.jdbc.OracleConnection;
// 接続を取得
Connection conn = DriverManager.getConnection(URL, USER, PASS);
OracleConnection ora = (OracleConnection) conn;
// セッション情報をクライアント側から設定
String[] metrics = new String[OracleConnection.END_TO_END_STATE_INDEX_MAX];
metrics[OracleConnection.END_TO_END_MODULE_INDEX] = "OrderAPI";
metrics[OracleConnection.END_TO_END_ACTION_INDEX] = "createOrder";
metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = traceId;
ora.setEndToEndMetrics(metrics, (short) 0);
// この接続で実行されるすべてのSQL/PL/SQLは
// V$SESSION の MODULE/ACTION/CLIENT_IDENTIFIER に上記が設定された状態で実行される
try (CallableStatement cs = conn.prepareCall("BEGIN pkg_order.create(?); END;")) {
cs.setLong(1, orderId);
cs.execute();
}
// 接続返却前にクリア
metrics[OracleConnection.END_TO_END_MODULE_INDEX] = null;
metrics[OracleConnection.END_TO_END_ACTION_INDEX] = null;
metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = null;
ora.setEndToEndMetrics(metrics, (short) 0);
コネクションプール環境での注意:プール返却時にsetEndToEndMetricsでnull設定するか、プール側で接続返却時に自動クリアする設定にしてください。クリアせず別ユーザに渡すと前ユーザのコンテキストが残って監査・トレース情報が混ざります。HikariCPなどはconnectionInitSqlやleakDetectionで対策できます。
運用で使える監視SQL7種
DBMS_APPLICATION_INFOで設定した情報をフル活用する監視SQLクエリを集めました。そのまま運用テンプレとして使えます。
-- ① 現在動いている全モジュール・アクションを俯瞰
SELECT s.username, s.sid, s.serial#,
s.module, s.action, s.client_identifier,
s.client_info, s.status,
s.last_call_et AS sec_in_call,
s.event AS wait_event
FROM v$session s
WHERE s.module IS NOT NULL
ORDER BY s.last_call_et DESC;
-- ② 進行中の長時間処理の進捗バー
SELECT sid, opname, target,
sofar, totalwork,
ROUND(sofar*100/NULLIF(totalwork,0), 1) AS pct,
elapsed_seconds AS elapsed_sec,
time_remaining AS eta_sec,
message
FROM v$session_longops
WHERE time_remaining > 0
ORDER BY start_time DESC;
-- ③ 特定モジュールの全実行を集計
SELECT module, action, COUNT(*) AS exec_cnt,
SUM(elapsed_time)/1e6 AS total_sec,
AVG(elapsed_time)/1e3 AS avg_ms,
MAX(elapsed_time)/1e3 AS max_ms
FROM v$sqlstats
WHERE module = 'BillingBatch'
GROUP BY module, action
ORDER BY total_sec DESC;
-- ④ 特定相関IDの追跡(過去24時間)
SELECT sample_time, module, action,
sql_id, event, session_state
FROM v$active_session_history
WHERE client_id = '&trace_id'
AND sample_time > SYSTIMESTAMP - INTERVAL '24' HOUR
ORDER BY sample_time;
-- ⑤ ロックで止まっているモジュールを特定
SELECT b.sid AS blocker_sid, b.module AS blocker_module,
w.sid AS waiter_sid, w.module AS waiter_module,
w.event, w.seconds_in_wait
FROM v$session w
JOIN v$session b ON b.sid = w.blocking_session
WHERE w.blocking_session IS NOT NULL;
-- ⑥ モジュール別の待機イベントランキング
SELECT module, event, COUNT(*) AS samples
FROM v$active_session_history
WHERE sample_time > SYSTIMESTAMP - INTERVAL '1' HOUR
AND module IS NOT NULL
AND session_state = 'WAITING'
GROUP BY module, event
ORDER BY samples DESC
FETCH FIRST 20 ROWS ONLY;
-- ⑦ クライアントID別のリソース消費(マルチテナント分析)
SELECT client_id,
COUNT(*) AS samples,
COUNT(DISTINCT session_id) AS sessions,
COUNT(DISTINCT sql_id) AS sql_count
FROM v$active_session_history
WHERE sample_time > SYSDATE - 1
AND client_id IS NOT NULL
GROUP BY client_id
ORDER BY samples DESC
FETCH FIRST 20 ROWS ONLY;
本番で踏むアンチパターン6選
① 例外時にクリアし忘れて古い情報が残る
SET_MODULE後に例外発生→クリアされず別の処理が始まると監視画面に「BillingBatch」のままの古い情報が表示されます。必ずラッパー化してEXCEPTION句でクリアを徹底してください。
② 全モジュールが「APPLICATION」の汎用名
「とりあえずSET_MODULE」で機能名を雑に設定するとAWRレポートで集計しても「APPLICATIONが80%」のような意味のない結果になります。機能ごとに固有の名前(OrderAPI/BillingBatchなど)を付ける運用ルールを作ってください。
③ コネクションプールで前ユーザの情報が残る
JDBCコネクションプール環境で接続返却時にSET_CLIENT_IDENTIFIERをクリアしないと、次のユーザに前ユーザのIDが見えるセキュリティ事故になります。プール側で自動クリアする設定を必ず入れてください。
④ SET_SESSION_LONGOPSを毎ループ呼ぶ
1件ごとに進捗報告するとOracleの内部更新オーバーヘッドが見えます。100〜1000件ごとに更新するか、時間ベース(5秒ごと)で更新する制御に切り替えてください。
⑤ アクション名にIDなどの可変値を入れる
SET_ACTION('Process_ORDER_12345')のようにIDをアクション名に入れるとAWRで集計したとき「Process_ORDER_12345」「Process_ORDER_12346」とバラバラになり集計不能。可変値はCLIENT_INFOに入れ、ACTIONには共通の処理名を入れてください。
⑥ 監視で使う前提なのに本番で設定していない
「障害時に追跡できる」の前提で運用設計したのに実装でDBMS_APPLICATION_INFOが呼ばれていないと、V$SESSIONのMODULEが空欄で何の役にも立たない監視画面になります。主要な処理の入口での設定をコードレビュー必須項目に。
よくある質問
setEndToEndMetricsまたは接続後にPL/SQLでSET_MODULEを呼ぶ必要があります。Springなら@Aspectでリクエストごとに自動設定するパターンが定番です。connectionInitSql等)でBEGIN DBMS_APPLICATION_INFO.SET_MODULE('YourApp', NULL); END;を初期化時に呼ぶと固定モジュール名を付けられます。sofar = totalworkにして最後に1回呼び出すと、進捗100%として表示されてから消えます。監視画面で「完了したかタイムアウトしたか」を区別したい場合に有用です。READ_MODULEで取得しないかぎり残りません。スタック式の管理が必要なら本記事のラッパー実装を参考にしてください。V$SESSION_LONGOPSを自動的に表示する画面を持っており、SET_SESSION_LONGOPSで出力された進捗が「Long Running Operations」としてリアルタイムに表示されます。バッチ処理を運用するチームでは管理画面に常時表示しておくと「夜間に止まったか動いてるか」が一目でわかり運用が楽になります。関連記事で深掘りする
監視・運用に関連する周辺技術もあわせて押さえましょう。
- 【Oracle】DBMS_APPLICATION_INFO完全ガイド(基本構文と機能網羅)
- 【PL/SQL】インストゥルメンテーション設計とログトレース手法(独自ログ機構との組み合わせ)
- 【Oracle】セッションの確認・強制切断方法(V$SESSION詳細)
- 【Oracle】待機イベント完全ガイド(モジュール別待機分析)
- 【PL/SQL】DBMS_PROFILERで行レベル分析する完全ガイド(プロファイラとの併用)
- 【PL/SQL】パフォーマンス改善プレイブック(性能改善の全体像)
- 【Oracle】AWR・ASHレポート完全ガイド(モジュール集計の活用)
- 【PL/SQL】AUTONOMOUS_TRANSACTIONで独立処理を実装する完全ガイド(独立ログとの組み合わせ)
- 【PL/SQL】DBMS_SCHEDULERでジョブ管理を極める(バッチ運用での監視連携)
- 【PL/SQL】パッケージ設計でコード管理と再利用性を極める(ラッパーパッケージの設計)
まとめ|DBMS_APPLICATION_INFOで運用観測性を底上げする
DBMS_APPLICATION_INFOは「タダで観測性を上げる」PL/SQL運用の基本装備です。オーバーヘッドゼロで本番常時ONできる軽さながら、V$SESSION・AWR・ASHでのモジュール集計、長時間処理の進捗可視化、分散トレースの相関ID連携、と運用に直結する効果を発揮します。本記事の要点を7つに集約します。
- 4つのAPI(MODULE/ACTION/CLIENT_INFO/CLIENT_IDENTIFIER)を用途別に使い分ける
- ラッパーパッケージで例外時もコンテキストを必ずクリアする
- SET_SESSION_LONGOPSで長時間処理の進捗バーを監視画面に表示する
- AWR/ASHはモジュール別に集計するため意味あるモジュール名を必ず設定
- CLIENT_IDENTIFIERにトレースIDを入れて分散トレース風に追跡する
- JDBC側でsetEndToEndMetricsを使えば自動連携できる
- コネクションプール返却時のクリアを忘れずセキュリティ事故を防ぐ
「夜間バッチが動いているか分からない」「重いSQLがどこから来たか追えない」という運用課題は、DBMS_APPLICATION_INFOを正しく使うだけで構造的に解消できます。本記事のラッパーパッケージと監視SQL集をテンプレとして自プロジェクトの観測性を底上げしてください。

