JavaでRDBデッドロック検出

  • 27
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

http://cs.hatenablog.jp/entry/2013/07/09/234554
RDB操作でデッドロックは不可避です。ご確認ください。

DBでのデッドロックの発生は、直ちにシステムが停止することを意味しません。DBMSはデッドロック発生を検出してトランザクションを失敗させる機能を持っているからです。
アプリケーションの開発者がすべきことはただ一点、 デッドロック検出時のリトライ です。更新処理だけじゃないです。参照処理でも忘れちゃいけません。約束です。

Javaの場合デッドロック発生はコード的にどう検知すればいいかというと、SQLExceptionが内部にSQLSTATEというRDB共通のエラー番号を持っているのでこれで判別可能となっています。
SQLSTATEの一覧は日立さんのこのまとめが役に立ちます。拝承。
http://www.hitachi.co.jp/Prod/comp/soft1/manual/pc/d635840/W3580048.HTM
デッドロック発生は 40001 ですね。

フレームワークによってはSQLExceptionでなくPersistenceExceptionを投げてきますが、大抵PersistenceExceptionは内部にSQLExceptionを抱えているので取り出して判定できます。

両方の場合の判別コードです。どうぞ。

try {
    // 永続化操作
} catch (SQLException sqle) {   // SQLExceptionを投げるフレームワークの場合
    if ("40001".equals((sqle).getSQLState())) {
        // デッドロック
    }
    else throw sqle;
} catch (PersistenceException pe) { // PersistenceExceptionを投げるフレームワークの場合
    Throwable cause = pe.getCause();
    if (cause instanceof SQLException && "40001".equals(((SQLException)cause).getSQLState())) {
        // デッドロック
    }
    else throw pe;
}

デッドロック発生の場合はそういう例外を自前で作ってさらに投げ出した方がよさげですね。