Enqueue

基本情報

 

Oracleは、Enqueueロックを利用して、オブジェクトを保護します。 Oracleは、特定のオブジェクトを使用するために、必ず、そのオブジェクトを保護するEnqueueロックを獲得しなければならりません。もしEnqueueロックを獲得できない場合enqueueイベントを待機します。 enqueue待機イベントは、Oracle 9iまで使用され、Oracleの10gからEnqueueロックによる待機現象は、すべての個別の待機イベントで分かれて定義されており、さらにロック競合が発生する状況別に分かれた場合もあります。例えばTXロックによる待機現象はenq:TX – row lock contention、enq:TX – allocate ITL entry、enq:TX – index contention、enq:TX – contention四つのイベントに区分されました。 V $ SESSION_WAITビューまたはV $ SESSIONビューを使用すると、現在のすべてのロックの競合が発生しているかどうか正確に知ることができます。 EVENT列の値が “enqueue”または “enq:XXX」の場合、Enqueueロックによる競合が発生するという意味です。 V $ SESSION_WAITビューのP1列の値がEnqueueロックの “name | mode」を意味します。次のようなSQLステートメントを利用して判読可能な値に変換することができるます。

 

SQL> select chr(bitand(P1,-16777216)/16777215) ||
chr(bitand(P1,16711680)/65535) "Name",
bitand(P1, 65535) "Mode"
from dual;

 

V$ SESSION_WAITビューのP2カラム、V$ LOCKのID1、P3カラムは、V$ LOCKのID2カラムと一致します。ID1、ID2の値はEnqueueロックの種類ごとに異なるのです。Oracle 10gのからV$ LOCK_TYPEビューを利用して、特定のEnqueueロックのID1とID2カラムの値の意味を知ることができます。 enqueue待機イベントを解消する方法は、競合が発生したEnqueueロックの種類に応じて異なります。

 

・TXロック - 低レベルロック競合
・TXロック - ITLエントリ不足
・TXロック - インデックスの分割
・STロック
・TMロック
・HWロック
・TCロック
・CIロック
・ROロック
・SQロック
・ULロック
・USロック

 

パラメータと待機時間

 

待機パラメータ

 

・P1:Enqueue情報
・P2:Enqueue Resource ID1
・P3:Enqueue Resource ID2

 

待機時間

 

最大3秒まで待ちます。もしEnqueueロックを獲得する場合、獲得するまで待機します。

 

チェックポイントとソリューション

 

Event Tip

 

ロックの分類

 

ロックは非常に簡単な概念であるが、実際にはかなり混乱する面があります。この混乱は、第一に、ロックの正確な分類が存在しないことと第二に、Enqueueロックと一般ロックとの正確な区分が存在しないことに起因します。この二つの問題を先に話題とします。 Oracle Conceptマニュアルでは、ロックを次のように分類しています。

 

・DML Lock
・Row Locks(TX)
・Table Locks(TM)
・DDL Lock
・Latches and Internal Locks
・Latches
・Internal Locks
・Dictionary Cache Locks
・File and Log Management Locks
・Tablespace and Rollback Segment Locks

 

上記の分類は非常に論理的な側面が強く、ロックの使用率を理解するには役立ちますが、ロックの実際の動作メカニズムを理解するには、むしろ混乱を招く側面があります。Steve Adamsは、自分の著書「Oracle8i Internal Services for Waits、Latches、Locks、and Memory」で次のようにロックを分類しています。

 

・Enqueue Locks
・Row Cache Enqueues
・Library Cache Locks and Pins
・DML Locks
・Buffer Locks
・Sort Locks

 

この分類は、基本的にEnqueueロックと一般ロックを区分し、一般的なロックを再row cache lock、library cache lock/ pin、dml lock、buffer lock、sort lockを区分しています。この分類の最も重要な基準は、Enqueue構造で管理されているロックとそうでないロックを区分することにあります。この区分を理解するためにEnqueueロックと一般ロックの違いを調べてみましょう。 EnqueueロックはEnqueue構造で管理されているロックを言います。Oracle 10gからほとんどのEnqueueロックについて個別待機イベントが登録されるので、v$ event_nameビューを照会するとどのような種類のEnqueueロック存在するか知ることができます。Enqueue構造体は、Shared Pool領域に保存され、次の図のような構造を有します。

 

My_enqueue

                                 図Enqueue構造

 

Enqueueロックは、リソースとして使用します。例えば一つのTMロックは、単一のテーブルを保護するために、このテーブルを一意に特定するリソース識別子(Resource Idenitifer)での値を使用します。一つのインスタンスに多くのEnqueueロック存在することができますので、図に示すように、ハッシュチェーン(Hash chain)構造を使用します。すなわち、リソース識別子にハッシュ関数を適用してバケット(Bucket)を割り当て、一つのバケットは、ハッシュチェーンの形で複数のリソース構造体を従えています。各リソース構造体は、リソース自体の情報と、このリソースのロックを保持しているプロセスのリスト、待機しているプロセスのリストを、ロックモードを変更したプロセスのリストを従えています。この構造を利用して、Oracleは、特定のリソースへの正確な同期機構を実装します。

 

一方、Enqueueロックと同じ目的を持ちながらも、他の方法で実装されているロックがあります。row cache lockが代表的な場合です。Shared PoolのRow Cache領域を保護するために、Oracleはrow cache lockを使用しますが、row cache lockはEnqueue領域で統合管理することなく、個々のRow Cacheメモリ領域自体に保持プロセスのリスト(Owner List)と待機プロセスのリスト(WaiterList)を管理します。このように動作するrow cache lock、library cache lock、library cache pin、buffer lockなどがあります。

 

ロック保護するリソース

 

ラッチがSGAを保護する場合、ロックは、データベース全体を保護することができます。テーブル、トランザクション、Undoセグメントと、表スペース、ジョブ(Job)などのデータベース単位で必要なほとんどのリソースは、ロックの保護を必要とする。

 

Enqueueロック保護するリソースは、リソース区切り文字として定義されます。ロックの名前がリソース名と一致しているという事実を忘れてみましょう。例えばTMロックはTM(テーブル)のリソースを保護します。TXロックはTX(Transaction)リソースを保護し、USロックはUS(Undo Segment)リソースを保護します。リソースセパレータを構成するID1とID2の値は、リソースの種類によって異なり、各リソースを一意に区別することができる値を使用します。代表的なリソースの種類とセパレータの意味は次のとおりです。

 

TM ロック: ID1=Object id
TX ロック: ID1=USN<<16|SLOT, ID2=Sequence
US ロック: ID1=USN
HW ロック: ID1=Tablespace#, ID2=DBA of Undo Segment Header
...

 

Enqueueロック競合が発生した場合、V $ LOCKビューのTYPE、ID1、ID2の値がリソースセパレータの役割をし、この値を用いて正確にどのようなリソースにロック競合が発生しているかどうかを観察することができます。 V $ SESSION_WAITビューのP1、P2、P3でも同じ情報を得ることができますが、P1 = name | modeであり、P2 = ID1、P3 = ID2の値です。

 

Enqueueロック以外の一般的なロックの場合には、別のリソース構造体が存在しないため、これを区別するためのリソース識別子も存在しません。また、V $ LOCKのような統合されたビューを介して観察することも不可能となります。一般ロックの発生状況と競合するかどうかを知ることができる最良の方法は、V $ SESSION_WAITビューで待機現象が発生していることを観察することです。例えばbuffer lock競合が発生した場合buffer busy waitsやread by other sessionイベントの待機現象が発生します。 row cache lock競合はrow cache lockイベントで、library cache lockとlibrary cache pinでの競合は、library cache lockイベントとlibrary cache pinイベントに観察されます。

 

ロック動作機構

ロックモード

ロック保護するリソースは非常に複雑な場合が多いので、このリソースを保護するための方法も複雑になるしかない。これらの複雑さを管理するために、Oracleはロックを獲得するモードを多様に構成します。ロック獲得時に使用可能なモードは次の通りです。

 

モード 説明
 0 None
 1 NUll(N)
 2 Sub-Shared(SS)またはRow-Shared(RS)
 3 Sub-Exclusive(SX)またはRow-Exclusive(RX)
 4 Shared(S)
 5

Shared-Sub-Exclusive(SSX)または

Shared-Row-Exclusive(SRX)

 6 Exclusive(X)

 

例えば、テーブルを変更しようとするプロセスは、そのテーブルに対してTMロックをExclusiveに獲得しなければなりません。テーブルに対してDMLを実行しようとするプロセスは、TMロックをSub-Exclusiveモードで獲得しなければならないのです。Sub-Exclusiveモード間での相互運用性があるため、同時に複数のプロセスが1つのテーブルに対してDMLを実行することが可能になります。 ロックモード間のように使用することができるかどうかをロックモードの互換性と呼び、Oracleはロックモードの互換性を利用して、リソースへの複雑な作業を同期します。

 

ロックモードの互換性

ロックモードの互換性を表にまとめた場合、以下の通りとなります。

 

 

N

SS SX S SSX X
N O O O O O O
SS

O

O O O O X
SX O O O O X X
S

O

O X O X X
SSX O O X X X X
X O X X X X X

 

ロックの競合を理解するには、ロックのモードとの互換性のために正確な理解が必要となります。例えば、特定のプロシージャを実行するプロセスは、プロシージャに対応するLibrary Cache Objectのlibrary cache pinをSharedモードで獲得しなければなりません。一方、プロシージャをコンパイルしようとするプロセスは、library cache pinをExclusiveに獲得しなければならりません。SharedモードとExclusiveモードでは、互換性がないため、トランザクションが旺盛なシステムでプロシージャをコンパイルすると、library cache pinによる競合が発生することになります。

 

ロック獲得

 

Enqueueロック獲得に失敗したプロセスは、自分自身をEnqueueリソースの待機リスト(Waiter List)に登録します。現在ロックを保持しているプロセスは、ロック使用後ロックを解除してEnqueueリソースの待機リストから次のプロセスを起動します。ロック獲得に失敗したプロセスは、待機リストに待機状態で登録され、特定のタイムアウト値を持つアラームを設定します。 Enqueueロックの場合には、タイムアウト時間は3秒です。もしロックを保持しているセッションが3秒後ロックを解除し起動されない場合、タイムアウトにより3秒後に自ら起動する。起動プロセスは、デッドロックが発生したかどうかを確認した後、再待機状態に戻ることになります。ロックを獲得するために待っている間、プロセスは、リソースの種類に応じて、enq:XX - YYYYYイベントを待機することになります。 Oracle 10gのからすべてのEnqueueリソースの種類ごとに別々の待機イベントを登録し、同じリソースタイプにも状況に応じて待機イベントを細分化して定義しています。仮に同じTXロック競合とも競合が発生する状況に応じてenq:TX - row lock contention、enq:TX - allocate ITL entry、enq:TX - index contention、enq:TX - contentionイベントが個別に定義されています。

 

Row cache lockのような一般的なロックもEnqueueロックと基本的に同じように動作します。ただし、ロックの種類に応じてタイムアウト時間がすべて異なっています。 Buffer lockは、一般的には、タイムアウトが1秒であるが、連続的にbuffer lockを獲得するために待機している場合には、3秒となります。 Row cache lockは60秒まで待ち、library cache lockとlibrary cache pinは一般的なプロセスでは、3秒を待ちますが、PMONプロセスの場合には、タイムアウトが1秒です。 ラッチは、レベルというメカニズムを介してデッドロックが発生することを根本的に防止しますが、ロックは、デッドロックの可能性が常に存在します。したがってロックを待機するプロセスは、決まった時間になると、すなわち、タイムアウトが発生すると、起動すべきデッドロックが発生したかどうかをチェックします。もしデッドロックに判定されると、デッドロックを検出したプロセスのロック要求はキャンセルされ、全体のトランザクションではなく、現在のSQLステートメントがロールバックされます。そしてalertログファイルにデッドロック情報を残します。

 

ロック関連Dynamic Views

 

Enqueueロックと関連した最高のビューは、V$ LOCKビューです。このビューをよく観察するとEnqueueロックと関連するすべての情報を得ることができます。したがって、このビューを正確に理解することが重要となります。 以下は同じロウの更新によってTXロック競合が発生した場合をV$ LOCKビューで観察した例となります。

 

SQL> select sid, type, ID1, ID2, lmode, request, ctime, block from v$lock where type = 'TX';

 

SID TYP        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------- --- ---------- ---------- ---------- ---------- ---------- -
143 TX      852011       9963          0          6         60          0
153 TX      852011       9963          6          0         69          1 

 

 

SID153のセッションは、リソースのExclusiveモード(lmode = 6)でロックを獲得したか69秒経過した他のロックをブロック(block = 1)しています。 SID143のセッションは、同じリソースに対してExclusiveモード(request = 6)にロックを要求したか、60秒経過しました。つまりSID153のセッションが獲得したTXロックは143番が要求しているTXロックを介してブロックしていることになります。

 

V $ LOCKED_OBJECTビューは、現在のシステムのすべてのトランザクションによって獲得されているTMロックに関する情報を提供します。このビューは、OBJECT_ID列を介して関連するオブジェクトを直感的に照会することができます。したがって、ロックかかったテーブルを照会するときに便利な機能です。 V $ ENQUEUE_LOCKビューはV $ LOCKビューとほぼ同じですが、実際のEnqueue現象、すなわちブロッキングが発生した場合、スタンバイ・セッションに関する情報だけを照会されます。つまりどのようなセッションがロックを待機するためにキューで待機しているかどうかの情報だけ出てくるのです。したがってV $ LOCKに比べて情報の範囲が狭くなります。ブロッキング関係を簡単に観察することができる他のビューは、DBA_WAITERSビューがあります。

 

ロックは、ラッチとは異なり、非常に多様なリソースを保護するため、正確な情報を得るために多くの情報を必要とします。リソースの種類に応じて、DBA_OBJECTS、DBA_TABLESPACES、V $ SESSION、V $ TRANSACTION、V $ UNDOSTAT、V $ SQLなど多くの種類のビューを一緒に観察する必要があります。

 

Enqueueロックでない場合には、V $ LOCKビューのような統合的なビューは存在しません。 library cache lockの場合には、DBA_DDL_LOCKSビューまたはDBA_KGLLOCKビュー、またはX $ KGLLKビューを使用して観察が可能となります。 library cache pinはDBA_KGLLOCKビューまたはX $ KGLPNビューを通じて観察可能です。メタリンクの文書番号122793.1にX $ KGLLKビューまたはX $ KGLPNビューを利用してlibrary cache lockとlibrary cache pinの競合関係を把握する方法がよく説明されています。 row cache lockの場合には、V $ ROWCACHE_PARENTビューを介して間接的な観察が可能です。バッファキャッシュダンプやrow cacheダンプ、library cacheダンプ、systemstateダンプなどを利用しても観察が可能ですが、テストや研究と障害解析用としてのみ活用可能です。