デッドロックの再現実験をやってみます。
デッドロックとはお互いがロックされているデータのロックが解除されるのを待っている状態です。
例えばセッションAとセッションBという2つのセッションが存在していたとします。
セッションA
UPDATE文により「region_id=1」がロックされました。
セッションB
UPDATE文により「region_id=2」がロックされました。
セッションA
UPDATEにより「region_id=2」をロックしようとしますが、すでにセッションBによりロックされているので待ちが発生します。
セッションB
UPDATEにより「region_id=1」をロックしようとしますが、すでにセッションAによりロックされているので待ちが発生します。
お互いがお互いのロック解除を待っている状態です。
いずれのセッションもトランザクションを終了できず、ロック競合を解消できません。
→デッドロックの発生です。
セッションA
デッドロックが発生した場合、最後のセッション(セッションB)でロックしようとしている行をロックしているセッション(セッションA)でエラーORA-00060が発生します。
結果として、セッションAの最後のSQL文がロールバックされます。
また、トランザクション全体をコミット、ロールバックすることでセッションBのロック待ちが解除されます。
セッションB
セッションAのrollback後、セッションBのロック待ちが解除され、UPDATE文が完了しました。
デッドロックとはお互いがロックされているデータのロックが解除されるのを待っている状態です。
例えばセッションAとセッションBという2つのセッションが存在していたとします。
セッションA
SQL> select * from hr.regions;
REGION_ID REGION_NAME
---------- ---------------------------------------------------------------------------
1 Europe
2 Americas
3 Asia
4 Middle East and Africa
SQL> UPDATE regions SET region_name='aaa'
2 WHERE region_id=1;
1行が更新されました。
SQL> select * from hr.regions;
REGION_ID REGION_NAME
---------- ---------------------------------------------------------------------------
1 aaa
2 Americas
3 Asia
4 Middle East and Africa UPDATE文により「region_id=1」がロックされました。
セッションB
SQL> select * from hr.regions;
REGION_ID REGION_NAME
---------- ---------------------------------------------------------------------------
1 Europe
2 Americas
3 Asia
4 Middle East and Africa
SQL> UPDATE regions SET region_name='bbb'
2 WHERE region_id=2;
1行が更新されました。
SQL> select * from hr.regions;
REGION_ID REGION_NAME
---------- ---------------------------------------------------------------------------
1 Europe
2 bbb
3 Asia
4 Middle East and Africa
UPDATE文により「region_id=2」がロックされました。
セッションA
SQL> UPDATE regions SET region_name='aaa'
2 WHERE region_id=2; UPDATEにより「region_id=2」をロックしようとしますが、すでにセッションBによりロックされているので待ちが発生します。
セッションB
SQL> UPDATE regions SET region_name='bbbb'
2 WHERE region_id=1; UPDATEにより「region_id=1」をロックしようとしますが、すでにセッションAによりロックされているので待ちが発生します。
お互いがお互いのロック解除を待っている状態です。
いずれのセッションもトランザクションを終了できず、ロック競合を解消できません。
→デッドロックの発生です。
セッションA
SQL> UPDATE regions SET region_name='aaa'
2 WHERE region_id=2;
UPDATE regions SET region_name='aaa'
*
行1でエラーが発生しました。:
ORA-00060: リソース待機の間にデッドロックが検出されました。
SQL> select * from hr.regions;
REGION_ID REGION_NAME
---------- ---------------------------------------------------------------------------
1 aaa
2 Americas
3 Asia
4 Middle East and Africa
SQL> rollback;
ロールバックが完了しました。
デッドロックが発生した場合、最後のセッション(セッションB)でロックしようとしている行をロックしているセッション(セッションA)でエラーORA-00060が発生します。
結果として、セッションAの最後のSQL文がロールバックされます。
また、トランザクション全体をコミット、ロールバックすることでセッションBのロック待ちが解除されます。
セッションB
SQL> UPDATE regions SET region_name='bbbb'
2 WHERE region_id=1;
1行が更新されました。
SQL> select * from hr.regions;
REGION_ID REGION_NAME
---------- ---------------------------------------------------------------------------
1 bbbb
2 bbb
3 Asia
4 Middle East and Africa セッションAのrollback後、セッションBのロック待ちが解除され、UPDATE文が完了しました。

コメント