読者です 読者をやめる 読者になる 読者になる

C Sharpens you up

http://qiita.com/yuba に移しつつあります

データベース操作でデッドロックは不可避

SQL

デッドロック発生させたと聞いただけで「うわ出たド素人」「それだけはないでしょ」「設計の仕方教わらなかったの?」と炎上3波目くらいまで装弾済みの怖い怖いお兄様方お姉様方こんばんは。

案外知られていないのでこの機会に確認しておいていただきたいのは
データベース操作でデッドロックは不可避
という事実です。大事なのでタイトルを繰り返させていただきました。

もう少し厳密に言うと、行書き込みロックからのロック拡大を伴うデータベース操作ではデッドロックは不可避、となります。テーブル同士のロック衝突だったらテーブルにロック順位をつけることで避けられるのですが、テーブル内の行同士には順位も何もありません。複数のスレッドが別々に行ロックを獲得したら、それを拡大してテーブルロックにしようとした時点で衝突となります。

そしてさらに。

実際のデータベース製品では行ロックの拡大をしていなくてもやはり避けられないロックに遭遇することがあります。デッドロック記録を解析してみるとなんとDBエンジンの内部オブジェクトがデッドロックに絡んでいるという、これはスキーマ設計ではどうしようもないというパターン。

これはこう解釈すべきでしょう、デッドロックはどうせ不可避だからエンジンの実装も「検出さえできればデッドロックは起こしてもかまわない」という思想に基づいていると。

そこであるべきデッドロックの扱い方です。MSDNも公式に

デッドロックを完全に回避することはできませんが、コーディング上の一定の規則に従うことにより、デッドロックが発生する可能性を最小限に抑えることができます。

デッドロックの最小化

防ぐんじゃない、減らせと言っています。それと、リトライですね。
デッドロック発生時のリトライの書き忘れは案外あります。特に参照系。参照系でリトライ忘れてるとお客さんに堂々と「データベースで異常が発生しています」なんてエラーメッセージをさらしちゃうことになるのでここほんと注意で。