- ベストアンサー
同じSELECT文同士でのデッドロックが発生する原因とは?
- ORACLE10Gを使用したアプリ開発中、同じ条件のSELECT文がパラレルで実行されるとデッドロックが発生してしまう問題に遭遇しました。
- 悲観的ロック(for update)しながら複数レコードを取得し、項目を更新するSQLを発行している中で、パラレル実行によるデッドロックを検出しました。
- 同じ条件による悲観的ロックであれば多重実行でも処理待ちをするだけだと考えていましたが、デッドロックが発生する原因について知りたいです。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
>2つの処理がロックしてしまう、というように聞こえますが >こういうことはあるんでしょうか? あるんです。Aのプロセスも、Bのプロセスも「誰もロックしてない」って思ってますから。 Aがロックを掛けた直後に、Bは「さっき調べた時は誰もロックしてなかったから、ロックしよう」と「上書きロック」をしてしまいます。 通常は1と3の間に2が割り込まず、2が後回しになる為、以下のようにAもBも正常終了します。 1.Aがレコードのロック状態を検査。ロック無しと判定 3.Aがレコードをロック 2.Bがレコードのロック状態を検査。ロック有りと判定 4.Bはレコードのロックが解除されるまで待ち合わせ (以下略) デットロックの直接の原因は「間に割り込みが入らず一連の動作として処理しなければならない、ロック状態の検査とロック設定の間に、別プロセスが割り込むため」です。 こういうケースは、データベースがサーバー上にあり、アクセスがネットを介して行われる場合で、2つのプロセスが同時に同じ処理を行った際に多発します。 回避には、独自にセマフォ変数やミューテックス変数を用意するなどして「データベースのロック機能以外を使って」排他制御が必要です。
その他の回答 (1)
- chie65536
- ベストアンサー率41% (2512/6032)
下記タイミングで処理されるとデットロックします。 1.Aがレコードのロック状態を検査。ロック無しと判定 2.Bがレコードのロック状態を検査。ロック無しと判定 3.Aがレコードをロック 4.Bがレコードを再ロック 5.Aが更新の為にレコード取得を試みる。が、4でBにロックされている為、ロックが解除されるまで処理待ち 6.Bが更新の為にレコード取得を試みる。が、3でAにロックされている為、ロックが解除されるまで処理待ち 7.めでたくデットロック 実際の処理では、レコードのロック以外に、テーブルのロック、システムテーブルのレコードロックとかも行うので、レコードロックとテーブルロックなどがかち合って、もっと楽しい事(※)が起きます(笑) (※)サーバーをリブートしないと復活しないとか、サーバーをリブートしても復活しないとか、色々。起きると死にそうな目に遭う。
お礼
ご回答ありがとうございます。 ちょっとだけ追加でご質問させてください。 >1.Aがレコードのロック状態を検査。ロック無しと判定 >2.Bがレコードのロック状態を検査。ロック無しと判定 >3.Aがレコードをロック >4.Bがレコードを再ロック というところですが、同時実行だと同一のレコードに対して 2つの処理がロックしてしまう、というように聞こえますが こういうことはあるんでしょうか? 私の記述がわかりにくかったかもしれませんが、 今回の対象は2つの処理で全く同じレコード郡に対しての 同時実行であった為です。 もし同時実行で後続の処理が同じレコードを 再ロックするなんてことがあるのならちょっと 考えないといけなそうなので^^;
お礼
ご回答ありがとうございます。 こういうことはDBMS上ありえないと勝手に思ってました。 おかげで対処できそうです。 色々ありがとうございました。