まず、select
ステートメントはOracleで何もロックせず、最後に使用可能な一貫したバージョンのデータを使用するだけです。 select ... for update
の場合はそうではありません update
のようなデータをロックします Oracle 9i以降ですが、更新用のfor update
質問からのクエリの句。
Resource Name process session holds waits process session holds waits
TM-000151a2-00000000 210 72 SX SSX 208 24 SX SSX
セッション#72は、「行排他」タイプ(SX)のテーブルレベルロック(TM)を保持しており、同じテーブルで「共有行排他」(SSX)ロックを取得したいと考えています。このセッションは、同じタイプ(SX)のテーブルレベルのロックをすでに保持していて、SSXロックが使用可能になるまで待機するセッション#24によってブロックされました。
Resource Name process session holds waits process session holds waits
TM-000151a2-00000000 208 24 SX SSX 210 72 SX SSX
これ(2行目)はまったく同じ状況を示していますが、反対方向です。セッション#24はSSXロックが使用可能になるのを待ちますが、同じテーブルでSXロックを既に保持しているセッション#72によってブロックされます。
したがって、セッション#24とセッション#72は互いにブロックします。デッドロックが発生します。
どちらのロックタイプ(SXとSSX)もテーブルレベルのロックです。
状況を理解するために、FranckPachotによるこの記事を読むことをお勧めします。
以下は、この記事からの引用であり、あなたの状況に直接関係しています(SSXとSRXの略語は同等であることに注意してください):
参照整合性もTMロックを取得します。たとえば、インデックス付けされていない外部キーの一般的な問題により、親テーブルでキーの削除または更新を発行すると、子テーブルでSロックが発生します。これは、インデックスがないため、参照整合性に違反する可能性のある同時挿入を防ぐために、Oracleにロックする単一の下位レベルのリソースがないためです。
外部キー列が通常のインデックスの先頭列である場合、最初のインデックスエントリは親値は単一のリソースとして使用でき、行レベルのTXlockでロックできます。
そして、参照整合性に削除カスケードがある場合はどうなりますか? Sモードに加えて、行X(RX)モードと同様に、子テーブルの行を更新する意図があります。ここで、共有行排他(SRX)が発生します:S + RX=SRX。
したがって、最も可能性の高いバリアントは、セッション#72とセッション#24がEMPLOYEE
の一部の行を削除することです。 同時にテーブルがあり、on delete cascade
があります EMPSAL_EMP_ID
の制約 EMPLOYEE_SALARY
にインデックスがないことに関連して EMPSAL_EMP_ID
が含まれるテーブル 最初にリストされている列。