【Oracle】ORA-06512の原因と読み方|at lineで本当のエラー箇所を特定する方法

【Oracle】ORA-06512の原因と読み方|at lineで本当のエラー箇所を特定する方法 Oracle

ORA-06512: at line n は、Oracle PL/SQLで例外が発生した時に表示されるスタック情報です。多くの場合、ORA-06512そのものが原因ではありません。直前に出ている ORA-06502ORA-01403ORA-01476ORA-20000 などが本当の原因で、ORA-06512は「どの行で発生し、どの呼び出し元へ伝わったか」を読むための情報です。

Oracle公式のエラー説明でも、ORA-06512はPL/SQLスタックの行番号を示すメッセージとして扱われます。そのため、対応ではORA-06512だけを直そうとせず、直前のエラー番号と at line の行をセットで確認します。

先に結論
ORA-06512が出たら、まずORA-06512の上にあるエラー番号を読みます。次に、最初の ORA-06512: at "スキーマ.オブジェクト", line n を見て、USER_SOURCE でその行を確認します。匿名ブロックの at line 1 だけを見ても、原因が分からないことが多いです。
スポンサーリンク

ORA-06512とは

ORA-06512は、PL/SQLの例外が発生した行と呼び出し経路を示す補助メッセージです。JavaやC#のスタックトレースに近い情報で、エラーの種類を表すメッセージではありません。

ora-06512-basic-message.txt
ORA-01476: divisor is equal to zero
ORA-06512: at "APP.P_CALC_RATE", line 8
ORA-06512: at "APP.P_MAIN", line 15
ORA-06512: at line 1
表示 意味 最初に見ること
ORA-01476 本当のエラー原因 ゼロ除算が起きた処理を探す
APP.P_CALC_RATE line 8 例外が発生した可能性が高い行 USER_SOURCEで行番号を確認する
APP.P_MAIN line 15 呼び出し元 どこから呼ばれたかを見る
at line 1 匿名ブロック側の呼び出し行 原因ではなく入口であることが多い

まず読むべき順番

ORA-06512は、上から順番に眺めるだけだと迷いやすいです。次の順番で読むと、原因と呼び出し元を切り分けやすくなります。

順番 見る場所 判断すること
1 ORA-06512より上のエラー番号 何が起きたかを判断する
2 最初のオブジェクト付きORA-06512 どのPL/SQLオブジェクトの何行目かを見る
3 後続のORA-06512 呼び出し元を順に追う
4 USER_SOURCE 該当行と前後のコードを確認する
5 ログ出力 FORMAT_ERROR_BACKTRACEで再現時の行番号を残す

特に重要なのは、最初に直すのはORA-06512行ではなく、ORA-06512より上にある原因エラーという点です。ORA-06512行は、原因エラーをどのソース行へ見に行くかを教えてくれる案内板として使います。

どの行を直すべきかの見分け方

複数のORA-06512が並ぶと、すべての行を直す必要があるように見えます。実際には、最初のオブジェクト付きORA-06512が発生元、その下のORA-06512は呼び出し元であることが多いです。

ORA-06512の行 役割 対応
一番上のオブジェクト付き行 例外が発生した処理に近い まずこのソース行と前後を読む
2番目以降のオブジェクト付き行 呼び出し元 入力値や呼び出し条件を確認する
at line 1at line 2 匿名ブロックやアプリ側の入口 原因行ではなく、呼び出し口として見る
RAISE_APPLICATION_ERROR の行 独自エラーを投げた場所 第3引数や元例外のログを確認する

at lineの読み方

at line n は、PL/SQLブロック内の行番号です。オブジェクト名が付いている場合は、そのプロシージャ、ファンクション、パッケージ本体などのソース行番号として読みます。オブジェクト名がなく at line 1 だけの場合は、SQL Developerやアプリが実行した匿名ブロックの行番号です。

anonymous-block-example.sql
BEGIN
  app.p_main;
END;
/

-- ORA-06512: at line 2
-- この場合は、匿名ブロック2行目の app.p_main 呼び出しで例外が外へ出たという意味

匿名ブロックの行番号だけでは、呼び出し先内部の原因までは分かりません。上に出ているオブジェクト付きのORA-06512、またはログに残したバックトレースを確認します。

USER_SOURCEで該当行を確認する

オブジェクト名と行番号が分かったら、USER_SOURCEALL_SOURCE で該当行の前後を確認します。行番号ぴったりの行だけでなく、条件分岐、直前の代入、SQL実行、例外再送出も見るのがコツです。

check-user-source-line.sql
SELECT line,
       text
FROM user_source
WHERE name = 'P_CALC_RATE'
  AND type = 'PROCEDURE'
  AND line BETWEEN 5 AND 11
ORDER BY line;
check-all-source-line.sql
SELECT owner,
       name,
       type,
       line,
       text
FROM all_source
WHERE owner = 'APP'
  AND name = 'P_CALC_RATE'
  AND line BETWEEN 5 AND 11
ORDER BY line;

ORA-06512と一緒に出やすいエラー

ORA-06512は、さまざまな実行時エラーの後ろに付きます。まず直前のエラー番号を読み、そのエラーの原因を直します。

直前のエラー 主な意味 関連記事
ORA-06502 数値または値のエラー。桁あふれ、文字列長不足、暗黙変換など ORA-06502の原因と解決方法
ORA-01403 SELECT INTOで行が見つからない ORA-01403 NO DATA FOUND
ORA-01422 SELECT INTOで複数行が返った ORA-01403・ORA-01422の対処
ORA-01476 ゼロ除算 ORA-01476の原因と解決方法
ORA-06550 PL/SQLコンパイルエラー ORA-06550の原因と読み方

呼び出し階層を読む例

次の例では、実際にゼロ除算が起きたのは P_CALC_RATE ですが、画面やバッチから見える入口は P_MAIN です。ORA-06512は、この呼び出し階層を順番に示します。

call-stack-example.sql
CREATE OR REPLACE PROCEDURE p_calc_rate IS
  v_rate NUMBER;
BEGIN
  v_rate := 100 / 0;
END;
/

CREATE OR REPLACE PROCEDURE p_main IS
BEGIN
  p_calc_rate;
END;
/

BEGIN
  p_main;
END;
/
call-stack-result.txt
ORA-01476: divisor is equal to zero
ORA-06512: at "APP.P_CALC_RATE", line 4
ORA-06512: at "APP.P_MAIN", line 3
ORA-06512: at line 2

この場合、最初に直す候補は P_CALC_RATE の4行目です。P_MAIN の3行目は、原因というより呼び出し元です。

FORMAT_ERROR_BACKTRACEでログに残す

本番運用では、画面に出たORA-06512だけでは情報が足りないことがあります。例外ログに DBMS_UTILITY.FORMAT_ERROR_STACKDBMS_UTILITY.FORMAT_ERROR_BACKTRACE を残すと、後から原因行を追いやすくなります。

format-error-backtrace.sql
BEGIN
  p_main;
EXCEPTION
  WHEN OTHERS THEN
    INSERT INTO error_log(error_message, error_backtrace, created_at)
    VALUES (
      DBMS_UTILITY.FORMAT_ERROR_STACK,
      DBMS_UTILITY.FORMAT_ERROR_BACKTRACE,
      SYSTIMESTAMP
    );
    RAISE;
END;

SQLERRM だけだと長いスタック情報を十分に残せないことがあります。ログ設計は DBMS_UTILITY完全ガイドPL/SQL例外処理ガイド も合わせて確認すると実装しやすいです。

RAISE_APPLICATION_ERRORとORA-06512

RAISE_APPLICATION_ERROR を使うと、アプリケーション独自の ORA-20000 番台エラーを返せます。ただし、例外の投げ直し方によって、元の行番号やスタックの見え方が変わります。

raise-application-error.sql
BEGIN
  p_calc_rate;
EXCEPTION
  WHEN OTHERS THEN
    RAISE_APPLICATION_ERROR(
      -20001,
      '計算処理でエラーが発生しました: ' || SQLERRM,
      TRUE
    );
END;

第3引数に TRUE を指定すると、既存のエラースタックに追加する形になります。利用者向けメッセージを整えつつ、調査に必要なORA-06512を残したい場合に有効です。逆に、何でも独自エラーに置き換えると、元の原因行が追いにくくなります。

投げ直し方 スタックの残り方 使いどころ
RAISE; 元の例外をそのまま再送出しやすい ログだけ残して原因を変えたくない時
RAISE_APPLICATION_ERROR(..., TRUE) 独自メッセージを追加しつつ既存スタックも残す アプリ向けメッセージと調査情報を両立したい時
RAISE_APPLICATION_ERROR(...) 独自エラー中心になり、元の情報が追いにくくなることがある 意図的に外部公開メッセージを絞る時
WHEN OTHERS THEN NULL 原因も行番号も失われる 原則避ける

WHEN OTHERSで原因を消していないか

ORA-06512の調査で特に危険なのが、WHEN OTHERS で例外を握りつぶす実装です。エラーを無視したり、固定メッセージだけを返したりすると、後から原因行を特定できません。

bad-when-others.sql
BEGIN
  p_main;
EXCEPTION
  WHEN OTHERS THEN
    NULL;
END;

-- 原因もORA-06512も消えてしまうため、調査が難しくなる
good-when-others.sql
BEGIN
  p_main;
EXCEPTION
  WHEN OTHERS THEN
    log_error(
      DBMS_UTILITY.FORMAT_ERROR_STACK,
      DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
    );
    RAISE;
END;

パッケージでline番号がずれるように見える場合

パッケージでは、仕様部ではなくパッケージ本体の行番号を見ていることがあります。PACKAGE BODY のソースを USER_SOURCE で確認し、該当行の前後も含めて読みます。再コンパイル後にソースが変わっている場合は、ログ発生時点のソースと現在のソースが一致しているかも確認します。

package-body-line-check.sql
SELECT line,
       text
FROM user_source
WHERE name = 'PKG_ORDER'
  AND type = 'PACKAGE BODY'
  AND line BETWEEN 120 AND 140
ORDER BY line;

パッケージ状態の破棄や再コンパイルが絡む場合は、ORA-04068の原因と対処 も関連します。

アプリケーションから見た時の注意点

Java、C#、PHP、PythonなどのアプリケーションでORA-06512を見る場合、ログにはDBから返ったエラーメッセージ全文を残します。先頭の1行だけを切り出すと、ORA-06512の行番号や呼び出し元が失われます。

確認項目 理由
DBエラーメッセージ全文を保存しているか ORA-06512行が欠けると原因行を追えない
バッチやAPIの入力値を保存しているか 同じPL/SQLでも入力値で発生箇所が変わる
接続ユーザーを記録しているか 参照先スキーマや権限差を切り分ける
例外を再ラップしていないか 元のOracleエラーが消えることがある

調査チェックリスト

項目 OKの状態
ORA-06512より上のエラーを読んだ ORA-06512だけで原因を判断していない
最初のオブジェクト付きORA-06512を見た 発生元のプロシージャやパッケージを特定した
USER_SOURCEで行番号を確認した 該当行と前後の処理を読んだ
呼び出し元を確認した どの画面、バッチ、APIから呼ばれたか分かる
FORMAT_ERROR_BACKTRACEを残した 再発時に原因行を追える
WHEN OTHERSを確認した 例外を握りつぶしていない

よくある質問

ORA-06512はエラーの原因ですか?

原因ではなく、PL/SQLのどの行を通って例外が伝わったかを示す情報です。原因は直前のORAエラーやPLSエラーに出ています。

ORA-06512: at line 1 は何を見ればよいですか?

匿名ブロックの1行目で呼び出した処理から例外が外へ出たという意味です。上に出ているオブジェクト付きORA-06512を優先して見ます。

行番号の場所に問題が見つかりません

該当行だけでなく、直前の代入、SQL、関数呼び出し、例外ハンドラを確認します。パッケージの場合はPACKAGE BODYを見ているかも確認してください。

本番ログにORA-06512が残っていません

アプリ側でエラーメッセージを短く切っているか、PL/SQL側で例外を握りつぶしている可能性があります。FORMAT_ERROR_BACKTRACEをログに残す設計にします。

まとめ

ORA-06512は、Oracle PL/SQLの例外発生行と呼び出し経路を示すスタック情報です。本当の原因は、ORA-06512より上に出ているエラー番号にあります。まず直前のエラーを読み、最初のオブジェクト付きORA-06512で発生元を特定し、USER_SOURCEALL_SOURCE で該当行を確認します。

本番運用では、DBMS_UTILITY.FORMAT_ERROR_BACKTRACE をログに残すと調査しやすくなります。ORA-06512を消してしまう例外処理を避け、原因エラーと行番号をセットで残すことが大切です。

参考

ORA-06512 – Oracle Database Error Help

PL/SQL Error Handling – Oracle Database PL/SQL Language Reference

DBMS_UTILITY – Oracle Database PL/SQL Packages and Types Reference