ロック

※ポイント※
     DML文を実行したときに取得されるロックの種類と、ロック競合が発生したときの監視方法が対象となる。
     ロック競合の中でも、特にデッドロックについては確認しておいた方がよい。

ロック

ロックとは、複数のセッションから同時にデータを変更されないようにレコードを保護するメカニズムである。
OracleサーバではDML文の発行時に、自動的に2種類のロックが取得される。

・行に対する排他行ロック
同じレコードに対するDML文が発行されることを防止する。
トランザクションが完了する前に同じレコードに対するDML文が発行されると、後からDML文を実行したセッションはロック待機状態となり、何も処理できなくなる。


・表に対する共有表ロック
同時にDDL文が発行されることを防止する。
DML文によるトランザクションが完了する前に同じテーブルに対するDDL文が発行されると、DDL文を実行したセッションに次のエラーが戻される。

SQL> TRUNCATE TABLE scott.emp;
TRUNCATE TABLE scott.emp
*
行1でエラーが発生しました。:
ORA-00054: リソース・ビジー、NOWAITが指定されていました。

レコードに対するロックは手動で行うこともできる。
本来はSELECT文はロックを取得しないが、次のようにFOR UPDATE句がある場合、問い合わせ結果のレコードに対して排他行ロックが取得される。

SQL> SELECT * FROM emp WHERE empno=7900 FOR UPDATE;

テーブルに対するロックも手動で行うことができる。
DML文発行時には、自動的に表に対して共有表ロックが取得されるが、次のようにLOCK TABLE文でEXCLUSIVEを指定すると、排他表ロックが取得される。

SQL> LOCK TABLE emp IN EXCLUSIVE MODE;

SELECT文とLOCK TABLE文でNOWAIT句を最後に付けると、ロックが取得できないときに、ロック待機するのではなくエラー(リソースビジー)として制御を戻すことができる。

ロック競合

 Oracleサーバにおけるロック管理は、「エンキューメカニズム」が担当している。エンキューメカニズムでは、次のことが追跡される。

* ロック待機中のセッション
* 要求されたロックモード
* セッションがロックを要求した順序

新規にロックを取得しようとすると、ロックのためのキュー(待ち行列)に追加される。
取得できなければロックが取得できるまでキューで待機する。
既存のロックがよりレベルの高いロックへの変換を必要とした場合は、キューに入り直すことなくロック変換が行える。

ロックの競合とは、同じリソースの取得を待ち合ってしまうことである。
ロック競合は、変更がコミットされずトランザクションが長くなってしまうと発生しやすいといえる。
また、LOCK TABLEやSELECT … FOR UPDATE文による手動ロックが不適切に使用されている場合も、ロック競合の原因となる。

※補足内容  デッドロックとは?

デッドロックは、複数のタスクが永久的に相互ブロックすることで発生する。
つまり、一方のタスクがロックを試みているリソースに他方のタスクがロックを保持していて、これが相互に行われるとデッドロックが発生します。次に例を示す。

* トランザクション A が行 1 の共有ロックを取得する。
* トランザクション B が行 2 の共有ロックを取得する。
* トランザクション A が行 2 の排他ロックを要求するが、トランザクション B が完了し、B が保持している行 2 の共有ロックが解放されるまで A はブロックされる。
* このとき、トランザクション B が行 1 の排他ロックを要求すると、トランザクション A が完了し、A が保持している行 1 の共有ロックが解放されるまで B はブロックされる。

トランザクション A は、トランザクション B が完了するまで完了できないが、
トランザクション B もトランザクション A によってブロックされる。
この状態は、循環依存関係とも呼ばれる。
トランザクション A がトランザクション B に依存し、トランザクション B がトランザクション A に依存するため、依存関係が循環する。
デッドロックになったどちらのトランザクションも、外部処理からデッドロックを解除されない限り、永久的に待機を続ける。

ロック競合の監視

ロック競合の確認には、Enterprise Manager、もしくはV$LOCKビューやV$LOCKED_OBJECTビューを使用する。
ロック競合が発生している場合、Enterprise Managerでは、ロック待機セッションがロック取得セッションのツリーに含まれる形で表示される。

デッドロック

デッドロックとは、複数のトランザクションが互いのロック解放を待ち合っている状態をいう。
Oracleサーバは、デッドロックを検出すると自動的に原因となる文をロールバックし、
明示的にトランザクションをロールバックするなどの処理が行えるようにしている。


エラー発生内容
詳細な情報を確認するためのファイルが
格納されるディレクトリを
指定している初期化パラメータ
解説

ORA-00060:
リソース待機の間にデッドロックが検出されました。
USER_DUMP_DEST デッドロックとは、複数のトランザクションが、別のトランザクションのリソース解放を待ち合ってしまうこと。
Oracleサーバでは、デッドロックが検出されると自動的に原因となった文をロールバックし、デッドロックを解放する。
ORA-00060エラーが検出されたセッションの処理を行っていたサーバプロセスにより、詳細情報がトレースされる。
従って、デッドロックが検出された場合の詳細情報は、ユーザートレースとして
USER_DUMP_DEST初期化パラメータで指定されたディレクトリに出力される。
なお、ORA-00060エラーが検出されたセッションに関しては、
トランザクションは続行しているため、ロールバックを手動で行い、トランザクションをやり直すことが推奨されている。
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License