【PL/SQL】DBMS_TRACEの使い方|呼び出し経路・例外発生箇所を追跡する方法

【PL/SQL】DBMS_TRACEで処理の実行経路を追跡する方法 PL/SQL

DBMS_TRACE は、PL/SQLのプロシージャ、ファンクション、例外、SQL、行番号の実行経路を追跡するためのOracle標準パッケージです。「どのサブプログラムがどの順番で呼ばれたか」「例外がどこで発生し、どこで処理されたか」を見たいときに役立ちます。

一方で、DBMS_TRACE は性能ボトルネックを測るための第一候補ではありません。時間や行別の実行回数を詳しく見たい場合は DBMS_PROFILER / DBMS_HPROF、運用監視で現在処理中のモジュールを見たい場合は DBMS_APPLICATION_INFO が向きます。この記事では、DBMS_TRACEを呼び出し経路と例外発生箇所の調査に絞って実務向けに整理します。性能分析は PL/SQLプロファイラ完全ガイド、運用観測性は DBMS_APPLICATION_INFO完全ガイド も参考にしてください。

この記事で扱うこと

  • DBMS_TRACE で分かること、分からないこと
  • tracetab.sql によるトレース表の準備
  • SET_PLSQL_TRACE / CLEAR_PLSQL_TRACE の基本
  • TRACE_LIMIT と enabled program unit によるデータ量制御
  • PLSQL_TRACE_RUNS / PLSQL_TRACE_UNITS / PLSQL_TRACE_EVENTS の読み方
  • 例外発生箇所を追うSQL
  • 本番利用時の注意点と削除方針
スポンサーリンク

DBMS_TRACEで分かること

DBMS_TRACEは、PL/SQLプログラムの実行中に発生した呼び出し、戻り、例外、SQL、行番号の変化をデータベース内の表に記録します。公式ドキュメントでも、PL/SQL関数・プロシージャ・例外をトレースするためのインターフェースとして説明されています。

呼び出し経路どのプロシージャやファンクションがどの順序で呼ばれたかを追えます。
例外例外がどこで発生し、どのハンドラで処理されたかを追跡できます。
行番号行トレースを有効にすると、行番号の変化を細かく記録できます。
注意点取得量が大きくなりやすいため、対象を絞って短時間だけ使います。

DBMS_PROFILERやログとの使い分け

DBMS_TRACEは「経路」を見る道具です。時間計測やボトルネック特定は、DBMS_PROFILERやDBMS_HPROFのほうが向いています。一方、業務ログや監査ログは、あとから運用上の事実を追うためのものです。目的ごとに使い分けます。

DBMS_TRACE呼び出し順、戻り、例外発生箇所、行番号の流れを確認したいとき。
DBMS_PROFILER / HPROFどの処理に時間がかかっているかを測定したいとき。
DBMS_APPLICATION_INFO実行中セッションのモジュール・アクション・進捗を運用監視したいとき。
業務ログ入力値、業務キー、処理結果、エラー内容を恒久的に残したいとき。

PL/SQL側の行レベル性能分析は DBMS_PROFILERで行レベル分析する完全ガイド、運用ログやトレーサビリティ設計は ロギングとトレーサビリティを両立する監査設計 が近いテーマです。

前提準備: tracetab.sqlを実行する

DBMS_TRACEの出力は、データベース内のトレース表へ保存されます。そのため、事前にOracle付属スクリプト tracetab.sql を実行して、PLSQL_TRACE_RUNSPLSQL_TRACE_UNITSPLSQL_TRACE_EVENTS などを作成しておく必要があります。公式ドキュメントでも、表がない場合はデータが収集されないと説明されています。

run-tracetab.sql
-- DBAまたは管理者が一度だけ実行する例
-- 環境によりパスは異なります
@$ORACLE_HOME/rdbms/admin/tracetab.sql

-- 作成後の確認例
SELECT table_name
FROM all_tables
WHERE table_name LIKE 'PLSQL_TRACE_%'
ORDER BY table_name;
注意: 本番環境では、トレース表の所有者、権限、保存期間、削除方針を決めてから使います。DBMS_TRACEは大量の行を出すことがあるため、表領域を圧迫しない運用が必要です。

最小手順: 有効化して対象処理を実行する

最小構成では、現在セッションでトレースを有効化し、対象処理を実行し、最後に必ず無効化します。CLEAR_PLSQL_TRACE を忘れると、想定外の処理まで記録されます。

dbms-trace-basic.sql
BEGIN
  DBMS_TRACE.SET_PLSQL_TRACE(
    DBMS_TRACE.TRACE_ALL_CALLS +
    DBMS_TRACE.TRACE_ALL_EXCEPTIONS
  );

  target_pkg.run_job(p_job_id => 1001);

  DBMS_TRACE.CLEAR_PLSQL_TRACE;
EXCEPTION
  WHEN OTHERS THEN
    DBMS_TRACE.CLEAR_PLSQL_TRACE;
    RAISE;
END;
/

例外時にも CLEAR_PLSQL_TRACE を呼ぶ形にしておくのが安全です。調査用SQLを何度も実行する場合は、この形をテンプレート化しておくとトレース停止漏れを防げます。

トレースレベルの選び方

DBMS_TRACEは、複数の定数を足し合わせてトレース対象を指定します。最初から全行・全SQLを取ると分析しづらい量になるため、まずは呼び出しと例外だけに絞るのがおすすめです。

TRACE_ALL_CALLS呼び出しと戻りを記録します。呼び出し経路を見る基本です。
TRACE_ALL_EXCEPTIONS例外の発生とハンドラを追跡します。
TRACE_ALL_SQLPL/SQLレベルのSQLを記録します。SQL Traceとは別物です。
TRACE_ALL_LINES行番号の変化を記録します。非常に多くなりやすいため短時間だけ使います。
TRACE_LIMIT直近の一定件数だけを残すための指定です。大量出力対策に使います。
NO_TRACE_HANDLED_EXCEPTIONS処理済み例外の収集を抑えたい場合に使います。
dbms-trace-levels.sql
-- 呼び出し経路と例外だけを見る
DBMS_TRACE.SET_PLSQL_TRACE(
  DBMS_TRACE.TRACE_ALL_CALLS +
  DBMS_TRACE.TRACE_ALL_EXCEPTIONS +
  DBMS_TRACE.TRACE_LIMIT
);

-- 行番号まで見る場合。短時間だけ使う
DBMS_TRACE.SET_PLSQL_TRACE(
  DBMS_TRACE.TRACE_ALL_LINES +
  DBMS_TRACE.TRACE_ALL_EXCEPTIONS +
  DBMS_TRACE.TRACE_LIMIT
);

対象を絞る: enabled program unit

大きなアプリケーションで全サブプログラムをトレースすると、データ量が膨らみます。DBMS_TRACEでは、特定のプログラムユニットをDEBUG付きでコンパイルし、TRACE_ENABLED_CALLSTRACE_ENABLED_EXCEPTIONS を使って対象を絞れます。

compile-debug-and-enabled-trace.sql
-- 対象パッケージだけDEBUG付きで再コンパイルする例
ALTER PACKAGE target_pkg COMPILE BODY DEBUG;

-- enabled program unit を中心にトレースする
BEGIN
  DBMS_TRACE.SET_PLSQL_TRACE(
    DBMS_TRACE.TRACE_ENABLED_CALLS +
    DBMS_TRACE.TRACE_ENABLED_EXCEPTIONS +
    DBMS_TRACE.TRACE_LIMIT
  );

  target_pkg.run_job(1001);

  DBMS_TRACE.CLEAR_PLSQL_TRACE;
END;
/

公式ドキュメントでは、全体をトレースすると管理しにくい大量データになるため、特定プログラムユニットへ絞る方法が案内されています。本番に近い環境では、まず対象パッケージを絞るのが現実的です。

直近のトレースランを確認する

トレース実行後は、まず直近のランを特定します。環境やバージョンにより列名の詳細は異なる場合がありますが、基本的には PLSQL_TRACE_RUNS から実行単位を確認し、RUNIDを起点にイベントやユニットを見ます。

find-latest-trace-run.sql
SELECT *
FROM (
  SELECT runid, run_date, run_owner, run_comment
  FROM plsql_trace_runs
  ORDER BY runid DESC
)
WHERE ROWNUM <= 5;

チーム運用では、トレース実行前にコメントや別途管理ログへ目的を残しておくと、あとから何の調査だったか分かりやすくなります。

呼び出し経路を読む

呼び出し経路を見るときは、イベント表とユニット表をRUNIDで結び、イベント順に並べます。コール、リターン、例外、行番号のどれを見たいかで絞り込みます。

read-trace-events.sql
SELECT
  e.runid,
  e.event_seq,
  e.event_kind,
  e.unit_owner,
  e.unit_name,
  e.line,
  e.depth
FROM plsql_trace_events e
WHERE e.runid = :runid
ORDER BY e.event_seq;

実際の列名やイベント値は環境により確認が必要です。まず DESC PLSQL_TRACE_EVENTS で列を確認し、自分の環境に合わせて分析SQLを調整してください。

例外発生箇所を追う

DBMS_TRACEの強い使いどころは、例外がどこで発生し、どこで処理されたかを追うことです。通常のログに「エラーになった」しか残っていない場合でも、トレースを取ると呼び出し経路と行番号の手がかりが得られます。

find-exception-events.sql
SELECT
  event_seq,
  event_kind,
  unit_owner,
  unit_name,
  line,
  exception_number,
  exception_name
FROM plsql_trace_events
WHERE runid = :runid
  AND (
    UPPER(event_kind) LIKE '%EXCEPTION%'
    OR exception_number IS NOT NULL
  )
ORDER BY event_seq;

コンパイルエラーや無効オブジェクトを疑う場合は、DBMS_TRACEより先に USER_ERRORSUSER_OBJECTS を確認します。そのあたりは PL/SQLコンパイル時エラーと警告の完全対処ガイド にまとめています。

行トレースは短時間だけ使う

TRACE_ALL_LINES は、行番号が変わるたびにレコードを追加します。細かい経路を追える反面、データ量が非常に増えます。広い範囲に対して長時間有効化するのではなく、再現手順を絞って短時間だけ使います。

line-trace-short-time.sql
BEGIN
  DBMS_TRACE.SET_PLSQL_TRACE(
    DBMS_TRACE.TRACE_ALL_LINES +
    DBMS_TRACE.TRACE_ALL_EXCEPTIONS +
    DBMS_TRACE.TRACE_LIMIT
  );

  -- 再現に必要な最小処理だけ実行する
  target_pkg.reproduce_error(p_id => 1001);

  DBMS_TRACE.CLEAR_PLSQL_TRACE;
EXCEPTION
  WHEN OTHERS THEN
    DBMS_TRACE.CLEAR_PLSQL_TRACE;
    RAISE;
END;
/

TRACE_LIMITで大量出力を抑える

TRACE_LIMIT を指定すると、直近の一定件数を残す形でデータ量を抑えられます。公式ドキュメントでは、問題箇所に至るまでの直近レコードを残し、大量の無関係データでデータベースを埋めないための指定として説明されています。再現直前にトレースを開始し、再現後すぐ停止する運用と組み合わせます。

trace-limit-example.sql
BEGIN
  DBMS_TRACE.SET_PLSQL_TRACE(
    DBMS_TRACE.TRACE_ALL_CALLS +
    DBMS_TRACE.TRACE_ALL_EXCEPTIONS +
    DBMS_TRACE.TRACE_LIMIT +
    DBMS_TRACE.NO_TRACE_ADMINISTRATIVE
  );

  target_pkg.run_job(1001);

  DBMS_TRACE.CLEAR_PLSQL_TRACE;
END;
/

トレース表を定期的に整理する

DBMS_TRACEの出力表は、調査のたびに増えます。開発環境でも、本番に近い検証環境でも、保存期間と削除方針を決めます。調査中のRUNIDを削除しないよう、古いRUNIDだけを対象にするなどのルールが必要です。

cleanup-trace-runs.sql
-- 例: 古いRUNIDを確認してから削除する
SELECT runid, run_date, run_owner, run_comment
FROM plsql_trace_runs
WHERE run_date < SYSDATE - 30
ORDER BY runid;

-- 実際の削除は環境の外部キー・権限・運用ルールに合わせて行う
-- 先にevents/unitsを消し、最後にrunsを消すなど、環境の定義を確認する
削除注意: トレース表はSYS所有で作られる構成もあります。権限や外部キー関係を確認せずに削除SQLを流さないでください。運用ルールに沿ってDBAと調整します。

本番で使うときの注意

DBMS_TRACEは便利ですが、本番で常時有効にするものではありません。調査対象、対象セッション、実行時間、取得レベル、停止手順、削除方針を決めてから使います。特に全呼び出し・全行・全SQLを広範囲に取ると、性能影響とデータ量の両方が問題になります。

対象を限定対象パッケージ、対象セッション、再現手順を絞ります。
短時間だけ取得再現直前に開始し、再現直後に停止します。
TRACE_LIMITを使う大量出力を防ぐため、必要に応じて直近レコードに絞ります。
共有サーバーに注意公式ドキュメントでは、shared server環境ではPL/SQL tracingを使えない制限があります。
ログと併用入力値や業務キーはDBMS_TRACEではなく、業務ログにも残します。

DBMS_APPLICATION_INFOと組み合わせる

DBMS_TRACEは調査時の詳細記録、DBMS_APPLICATION_INFOは普段の運用監視に向いています。PL/SQLバッチでは、通常時はモジュール・アクションを設定し、障害調査時だけDBMS_TRACEを使う構成が扱いやすいです。

application-info-with-trace.sql
BEGIN
  DBMS_APPLICATION_INFO.SET_MODULE(
    module_name => 'BATCH_ORDER_IMPORT',
    action_name => 'VALIDATE_INPUT'
  );

  order_import_pkg.validate_input(p_batch_id => 1001);

  DBMS_APPLICATION_INFO.SET_ACTION('IMPORT_DATA');
  order_import_pkg.import_data(p_batch_id => 1001);
END;
/

PL/SQLで運用観測性を高める実装は DBMS_APPLICATION_INFOで運用観測性を底上げ でも詳しく扱っています。

トラブルシュート

トレース表に行が出ないtracetab.sql が実行済みか、対象セッションでSET_PLSQL_TRACEしているか確認します。
行が多すぎるTRACE_LIMIT、enabled program unit、短時間実行で絞ります。
例外が見えないTRACE_ALL_EXCEPTIONS または TRACE_ENABLED_EXCEPTIONS が指定されているか確認します。
性能が気になるDBMS_TRACEではなくDBMS_PROFILER/HPROFで測るべき調査か切り分けます。
権限エラーDBMS_TRACE実行権限、トレース表参照権限、対象オブジェクトの権限を確認します。

よくある質問

Q. DBMS_TRACEは性能分析に使うものですか?
A. 主目的は呼び出し経路や例外の追跡です。時間のボトルネックを見るならDBMS_PROFILERやDBMS_HPROFが向いています。
Q. SQL Traceとは違いますか?
A. 違います。DBMS_TRACEはPL/SQLレベルのトレースです。SQL実行計画や待機イベントの詳細調査とは目的が異なります。
Q. 本番で使えますか?
A. 使えますが、対象・時間・レベルを絞り、TRACE_LIMITや削除方針を決めてから使います。常時有効化は避けます。
Q. トレース表は自動で作られますか?
A. 自動ではありません。事前にtracetab.sqlを実行して、DBMS_TRACEが出力する表を作成しておく必要があります。
Q. 業務キーや入力値もDBMS_TRACEで分かりますか?
A. 基本的には呼び出し経路や行番号の情報です。業務キーや入力値はアプリケーションログや監査ログに残してください。

まとめ

DBMS_TRACE は、PL/SQLの呼び出し経路、例外発生箇所、行番号の流れを追うための調査ツールです。事前に tracetab.sql でトレース表を用意し、SET_PLSQL_TRACE で有効化し、対象処理を実行したら CLEAR_PLSQL_TRACE で必ず停止します。

使うときは、最初から全行・全SQLを取らず、呼び出しと例外を中心に短時間だけ取得します。必要に応じて TRACE_LIMIT や enabled program unit を使い、データ量を抑えましょう。性能測定はDBMS_PROFILER/HPROF、運用監視はDBMS_APPLICATION_INFO、業務キーの追跡はログ設計、と役割分担すると、DBMS_TRACEを過不足なく使えます。

参考: Oracle Database PL/SQL Packages and Types Reference – DBMS_TRACE