◀ 15.

Db2エラー一覧|SQL0911Nの理由コード・SQL0805Nと安全な調査

▶

Db2 LUWのエラーは番号だけで対処を決めず、理由・接続先・トランザクションの状態を確認します。設定変更や権限付与より前に行う診断を整理します。

Db2エラーの番号と理由を読み原因を調べてから再試行を判断する図

この記事の要点
  • Db2 のエラーは SQLCODE (数値) と SQLSTATE (英数字5文字) のペアで返る。クライアントに表示されるのは SQL0911N のような形式
  • 末尾の N = エラー、W = 警告、C = 致命的システムエラー
  • 代表例: SQL0911N デッドロック/タイムアウト / SQL0204N 未定義オブジェクト / SQL0303N 型変換不可 / SQL0805N パッケージ見つからない
  • メッセージ参照は db2 ? SQL0911N で製品に付属する説明を参照できる
  • 網羅は IBM Documentation (旧 Knowledge Center) の「SQL message reference」を参照

Db2 エラーの読み方

SQL0911NはメッセージID、符号付き整数のSQLCODEは-911です。次の旧表示例の「SQLCODE: 文字列形式の番号」は誤記として読み替えてください。SQLSTATEは5文字の分類で、理由コードとは別です。

SQL0911N  The current transaction has been rolled back because of a deadlock
          or timeout.  Reason code "2".  SQLSTATE=40001
          ^^^^^^^^                                       ^^^^^
          SQLCODE: 文字列形式の番号                          SQLSTATE: 5 桁

SQLCODE  ... マイナス値はエラー、プラス値は警告、0 は正常
SQLSTATE ... SQL 標準準拠の 5 桁コード (40001 = serialization failure)
末尾    ... N (Error) / W (Warning) / C (Critical system error)

SQLSTATEが同じでも、原因・巻き戻し範囲・適切な対処が同じとは限りません。メッセージID、符号付きSQLCODE、SQLSTATE、理由コードを組で確認します。標準の分類を使える場合もありますが、他DBへ移して同じ分岐で正しく動く保証にはなりません。

頻出エラー一覧

メッセージIDSQLSTATE意味典型原因
SQL0911N40001デッドロック または ロックタイムアウト2 つ以上のセッションが互いを待つ / 長時間ロック保持
SQL0913N57033デッドロック/タイムアウト等による失敗理由コードとトランザクション管理方式を確認。SQL0911Nと巻き戻し範囲を同一視しない
SQL0204N42704オブジェクト (表 / ビュー / インデックス) 未定義接続先/スキーマ/識別子等を確認。別所有者というだけで未定義とは限らない
SQL0206N42703指定位置で名前が有効でない列名/別名/参照できる範囲等。列の不存在だけに限定しない
SQL0303N42806FETCH/SELECT の 結果型が変数型と一致しないVARCHAR 列を INT 変数で受ける等
SQL0407N23502NULL 値を NOT NULL 列に入れた必須項目に値を渡し忘れ
SQL0530N23503外部キー違反親側に存在しない値で子側を更新
SQL0532N23504削除制約違反 (RESTRICT / NO ACTION)子から参照されている親行を削除
SQL0803N23505一意制約違反主キー / UNIQUE 索引重複
SQL0805N51002パッケージ (静的 SQL) が見つからないBIND されていない / NULLID 等の指定誤り
SQL5005C-DBM/DB構成ファイルへアクセスできない対象ファイル・権限・使用中のDb2コピー等を確認。破損や起動失敗だけに限定しない
SQL0964C57011トランザクション ログ満杯未完了の長い/大きいトランザクション等。LOGSECONDを含むログ構成と使用状況を確認
SQL0901N58004システムエラー (継続可能)理由と診断情報から調査。再実行で直ると決めつけない
SQL0104N42601構文エラーキーワード綴り / カンマ落ち / カッコ閉じ忘れ

エラー番号からメッセージ詳細を引く

Db2 クライアントには ? コマンドが組み込まれており、エラー番号の説明文と推奨対応を表示できます。

$ db2 ? SQL0911N

SQL0911N  The current transaction has been rolled back because of a
          deadlock or timeout.  Reason code "<reason-code>".

Explanation: The current unit of work was involved in an unresolved
contention for use of an object and had to be rolled back. ...

User Response: To prevent this error, ...

# 数字だけでも引ける
$ db2 ? 911

# SQLSTATE からも
$ db2 ? 40001

SQL0911N の調査手順 (デッドロック)

SQL0911Nはデッドロックだけではありません。SQLCODE -911、SQLSTATE 40001と一緒に返る理由を読み、原因を分けます。以下は代表例で、すべての理由を列挙した表ではありません。

Reason Code意味
2デッドロック
68ロックタイムアウト
72旧Data Links Manager関連のエラー。通常のロック取得失敗へ一般化しない。対象製品版のメッセージ説明を確認

次の旧監視例はそのまま実行しないでください。LOCKTIMEOUTはDB構成なのでGET DBM CFGではなくGET DB CFG FORで確認します。grepとパイプはシェル構文で、SQLではありません。イベントモニターの作成/有効化はDBへの変更と収集負荷・保存容量を伴います。また、下のSYSIBMADM参照を「このイベントモニターが作った履歴表」と扱えません。既存の収集設定と利用可能な監視ビュー/関数を版・権限に合わせ確認します。UPDATE DB CFGによる60秒への変更は一律の解決策ではありません。

-- デッドロック / タイムアウトのイベントモニタを有効化
CREATE EVENT MONITOR DLMON FOR LOCKING WRITE TO TABLE;
SET EVENT MONITOR DLMON STATE 1;

-- 発生時はイベント表に履歴が残る
SELECT * FROM SYSIBMADM.SNAP_LOCKS_RPT;
SELECT * FROM SYSIBMADM.LOCKWAIT;

-- ロックタイムアウト時間の確認 / 延長 (秒、-1 は無限待ち)
GET DBM CFG | grep -i LOCKTIMEOUT
UPDATE DB CFG FOR MYDB USING LOCKTIMEOUT 60;

SQL0204N (未定義オブジェクト) の調査

最初にDB別名・CURRENT SCHEMA・修飾名と識別子の大小文字を照合します。SYSCAT.TABLESの検索は表/ビュー等の確認用で、すべての種類のオブジェクトを調べるSQLではありません。下のSELECTは実データを読み、1行でもSELECT権限が必要です。SET CURRENT SCHEMAはその接続での名前解決を変える操作で、所有者や権限を変えません。存在/権限/接続先の誤りを一律にSETで直さないでください。

-- オブジェクト存在確認
SELECT TABSCHEMA, TABNAME
FROM   SYSCAT.TABLES
WHERE  TABNAME = 'ORDERS';

-- スキーマを指定して再実行
SELECT * FROM MYAPP.ORDERS FETCH FIRST 1 ROWS ONLY;

-- 現在のスキーマ
VALUES CURRENT SCHEMA;

-- 既定スキーマを明示的に切替
SET CURRENT SCHEMA = MYAPP;

SQL0805N (パッケージ未 BIND) の対処

まず不足したパッケージのスキーマ・名前・版/整合性トークンと、使用するドライバーの種類/版を記録し、対象DBのカタログと照合します。未BINDだけでなく、参照するコレクションや版が違う場合もあります。

下の旧例は一括実行しません。db2cli.lstはCLI向けで、db2ubind.lstを一律に「JDBC用」とする説明は不正確です。JDBC/接続先に適合するファイルと対象パッケージを確認してください。BINDはDBを変更し、GRANT PUBLICは広い利用者へ権限を与えるため、障害調査の初手にしません。必要なBIND/実行権限を管理者と確認し、承認された対象と権限に限定します。CLIPKG増量もstatementの解放漏れ等を調べてから判断します。

$ db2 connect to MYDB
$ cd $HOME/sqllib/bnd

# CLI ドライバ用パッケージを BIND
$ db2 bind @db2cli.lst grant public CLIPKG 5

# JDBC 用
$ db2 bind @db2ubind.lst grant public
$ db2 bind @db2cli.lst   grant public

$ db2 terminate

アプリ側 (Java / JDBC) でのハンドリング

下の旧コードは完成したリトライ処理ではありません。40001だけでretry()せず、-911の理由とロールバックを確認し、再実行するならトランザクション全体を対象にします。メール/決済/外部API等の副作用があれば、DBの巻き戻しだけで再送安全とは判断できません。-913、接続断、COMMIT結果不明は別途調査します。

SQLException.getMessage()にはSQLや内部名・値が含まれ得るため、DuplicateException(msg)のようにそのまま画面へ流しません。利用者向けの固定文言/問い合わせIDと、アクセス制限された診断情報を分けます。-407も必ず利用者の入力漏れとは限らず、SQL/DEFAULT/バインド等を確認します。

try {
    pstmt.executeUpdate();
} catch (SQLException e) {
    int code = e.getErrorCode();        // SQLCODE (符号付き整数)
    String state = e.getSQLState();     // SQLSTATE
    String msg   = e.getMessage();

    if ("40001".equals(state)) {
        // デッドロック / シリアライゼーション失敗 → リトライ
        retry();
    } else if ("23505".equals(state)) {
        // 一意制約違反 → ユーザに重複と表示
        throw new DuplicateException(msg);
    } else if (code == -407) {
        // NOT NULL 違反
        throw new ValidationException("必須項目未入力");
    } else {
        throw e;
    }
}

網羅性のあるリファレンス

  • IBM Documentation (旧 Knowledge Center) の「Db2 message reference」: 製品/版に対応するSQLメッセージを参照
  • db2diag.log: 診断ログ。保存先はDBM構成のDIAGPATH等を確認し、固定のホーム配下と決めつけない。秘密値を含み得るため丸ごと公開しない
  • db2pd -d MYDB -locks: ロック状況のスナップショット

FAQ

Q: SQLCODE と SQLSTATE のどちらを見るべき?
A: SQLSTATEで分類しつつSQLCODE・理由・実際の処理状態を確認します。標準分類が共通でも、製品ごとの発生条件や巻き戻し範囲、ドライバーの例外を検証せず移植しません。

Q: SQL0911N が頻発する
A: 理由2と68をまず区別します。更新順序を揃える、トランザクションを適切に短くする等は対策候補ですが、索引・制約・トリガー・実行計画等にも左右され、同じ表順序だけで根絶できません。タイムアウトの延長だけで待ち原因を解消したことにもなりません。

Q: 末尾の W は気にしなくていい?
A: 警告は一律に無視せず、何が成功し何が変換/切り捨てされたかを確認します。正常終了・該当なし・警告をメッセージ末尾だけで一律に業務成功/失敗へ変換せず、呼び出しAPIの返却条件も確認してください。

設定を変える前の確認順

  1. 発生時刻、対象DB/製品版/ドライバー、メッセージID・SQLCODE・SQLSTATE・理由を控える。SQL全文や値を公開チケットへ貼らない。
  2. 対象環境のCLPでdb2 "? SQL0911N"を参照する。引用符はシェルが?を展開しないための例。下の旧ヘルプ表示は製品/版により異なる。
  3. シェルではdb2 get db cfg for MYDBの出力からLOCKTIMEOUTを確認する。MYDBは確認済みのDB別名へ置き換える。DB設定とは別に、そのアプリ接続のCURRENT LOCK TIMEOUTも確認する。
  4. 理由2なら競合する処理/取得順序、68なら待つ側と保持側・保持時間・未完了処理を調べる。事後のロック一覧だけでは過去の競合を再現できない。
  5. 収集を増やす場合は承認・保存先・容量・秘密値のマスクを先に決める。ログを消す、セッションを切断する、時間/権限/ログ容量を変える操作は診断と分ける。

SQL0964CはLOGPRIMARYだけの計算で説明せず、LOGSECONDや長時間未完了の処理、既存のADM1823E等を調べます。ログファイルの手動削除は対処にしません。SQL5005Cも構成ファイルを再作成/削除する前にアクセス不能の原因を調べます。

再実行の候補を絞るJava例

次はJava標準APIだけを使う、保守的な判定部品です。trueでも自動実行せず、トランザクション全体の再実行を検討できる候補という意味です。reasonはドライバー/診断情報で確認した値を渡し、メッセージの部分一致で推測しません。rollbackConfirmedとreplaySafeも呼出側で根拠を確認し、不明ならfalseにします。連鎖例外がある場合もこの例は保留にします。

import java.sql.SQLException;

/** A conservative review gate, not a transaction/retry implementation. */
public final class RetryGate {
    private RetryGate() {}

    public static boolean mayReviewReplay(SQLException failure, int reason,
            boolean rollbackConfirmed, boolean replaySafe, int failuresSoFar) {
        return failure != null
                && failure.getNextException() == null
                && failure.getErrorCode() == -911
                && "40001".equals(failure.getSQLState())
                && (reason == 2 || reason == 68)
                && rollbackConfirmed && replaySafe
                && failuresSoFar >= 1 && failuresSoFar < 3;
    }
}

failuresSoFarは初回失敗を1と数え、この例の上限は合計3試行です。実装時は待機の上限・バックオフ/ジッター・全体タイムアウトと中断、枯渇時の扱いを別に設計します。判定だけではrollback、再接続、二重実行防止、分散トランザクションを実装したことになりません。Db2実機の例外/巻き戻しは未検証で、掲載関数の条件分岐をオフライン検査した例です。

関連:Db2の子ページ一覧 / 接続先の確認 / DDL抽出と適用の区別。

公式:SQLメッセージ / ロック待機とタイムアウト / タイムアウト調査 / SQL5005C / ログ満杯。

子ページ
  1. SQL3100W Column number XXX in row XXX is missing in the input file, but the target column is not nullable.
同階層のページ
  1. DB接続コマンド
  2. データベース一覧の確認
  3. テーブル一覧の確認
  4. テーブル定義の確認
  5. DBの設定確認
  6. テーブルスペースの容量の確認および拡張
  7. データ型
  8. 複数カラムのUPDATE
  9. カラムの追加/削除/変更
  10. 自動番号付け (autoincrement) する方法
  11. インデックスの作成
  12. シーケンスおよびインクリメント(ID列)の違いと確認方法
  13. create table文の生成
  14. 特定スキーマの全テーブルの全カラム情報を取得する方法
  15. 【DB2】エラー一覧
  16. 【DB2】テーブル定義からCREATE TABLE文を生成する方法

最近更新/作成されたページ