アプリ版:「スタンプのみでお礼する」機能のリリースについて

ORACLE10Gを使用したアプリ開発中です。

アプリ中、1テーブルに対して全く同じ条件で
複数レコードを悲観的ロック(for update)しながら取得し、
項目を更新するSQLを発行します。

単発では問題なかったのですが、処理時間の関係で
パラレルで実行された場合にデッドロックを検出することがあります。

ORACLEのudumpの中を確認すると全く同じSELECTのSQL同士で
デッドロックが発生したと表示されています。

こういった場合、どういう原因が考えられるでしょうか?
(同じ条件による悲観的ロックであれば多重実行でも
 処理待ちをするだけだと思っているのですが・・・)

よろしくお願いします。

A 回答 (2件)

>2つの処理がロックしてしまう、というように聞こえますが


>こういうことはあるんでしょうか?
あるんです。Aのプロセスも、Bのプロセスも「誰もロックしてない」って思ってますから。
Aがロックを掛けた直後に、Bは「さっき調べた時は誰もロックしてなかったから、ロックしよう」と「上書きロック」をしてしまいます。

通常は1と3の間に2が割り込まず、2が後回しになる為、以下のようにAもBも正常終了します。
1.Aがレコードのロック状態を検査。ロック無しと判定
3.Aがレコードをロック
2.Bがレコードのロック状態を検査。ロック有りと判定
4.Bはレコードのロックが解除されるまで待ち合わせ
(以下略)

デットロックの直接の原因は「間に割り込みが入らず一連の動作として処理しなければならない、ロック状態の検査とロック設定の間に、別プロセスが割り込むため」です。

こういうケースは、データベースがサーバー上にあり、アクセスがネットを介して行われる場合で、2つのプロセスが同時に同じ処理を行った際に多発します。

回避には、独自にセマフォ変数やミューテックス変数を用意するなどして「データベースのロック機能以外を使って」排他制御が必要です。
    • good
    • 1
この回答へのお礼

ご回答ありがとうございます。

こういうことはDBMS上ありえないと勝手に思ってました。
おかげで対処できそうです。
色々ありがとうございました。

お礼日時:2007/10/02 17:11

下記タイミングで処理されるとデットロックします。



1.Aがレコードのロック状態を検査。ロック無しと判定
2.Bがレコードのロック状態を検査。ロック無しと判定
3.Aがレコードをロック
4.Bがレコードを再ロック
5.Aが更新の為にレコード取得を試みる。が、4でBにロックされている為、ロックが解除されるまで処理待ち
6.Bが更新の為にレコード取得を試みる。が、3でAにロックされている為、ロックが解除されるまで処理待ち
7.めでたくデットロック

実際の処理では、レコードのロック以外に、テーブルのロック、システムテーブルのレコードロックとかも行うので、レコードロックとテーブルロックなどがかち合って、もっと楽しい事(※)が起きます(笑)

(※)サーバーをリブートしないと復活しないとか、サーバーをリブートしても復活しないとか、色々。起きると死にそうな目に遭う。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

ちょっとだけ追加でご質問させてください。

>1.Aがレコードのロック状態を検査。ロック無しと判定
>2.Bがレコードのロック状態を検査。ロック無しと判定
>3.Aがレコードをロック
>4.Bがレコードを再ロック

というところですが、同時実行だと同一のレコードに対して
2つの処理がロックしてしまう、というように聞こえますが
こういうことはあるんでしょうか?

私の記述がわかりにくかったかもしれませんが、
今回の対象は2つの処理で全く同じレコード郡に対しての
同時実行であった為です。

もし同時実行で後続の処理が同じレコードを
再ロックするなんてことがあるのならちょっと
考えないといけなそうなので^^;

お礼日時:2007/10/01 18:16

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す