DML操作での自動ロック

DMLロック(データ・ロックとも呼ぶ)の目的は、複数のユーザーが同時にアクセスするデータの整合性を保証することです。たとえば、DMLロックを使用すると、オンライン・ブックショップで在庫が残り1冊となった本を複数の顧客が購入してしまうことを回避できます。DMLロックは、同時に実行される矛盾する複数のDML操作またはDDL操作の破損を招く干渉を防ぎます。

DML文では、表レベルと行レベルの両方のロックが自動的に取得されます。次の各項で、それぞれのタイプのロックまたはロック・モードの後のカッコ内にある頭字語は、Oracle Enterprise Managerのロック・モニターで使用される略称です。Enterprise Managerでは、表ロックのモード(RS、SRXなど)が示されるかわりに、すべての表ロックについてTMと表示される場合があります。

次に、行ロックおよび表ロックのタイプの概要を示します。行ロックおよび表ロックのタイプの詳細は、『Oracle Database概要』を参照してください。

行ロック(TX)

行ロックは、TXロックとも呼ばれ、表の単一の行に対するロックです。INSERTUPDATEDELETEMERGEおよびSELECT ... FOR UPDATE文のいずれかで変更される行ごとに、トランザクションは行ロックを取得します。行ロックは、トランザクションがコミットされるかロールバックされるまで保持されます。

ある行について行ロックを取得したトランザクションは、その行に対応する表についての表ロックも取得します。表ロックがあると、現行のトランザクションでのデータ変更をオーバーライドするDDL操作の競合が回避されます。

表ロック(TM)

INSERTUPDATEDELETEMERGEおよびSELECT ... FOR UPDATE文で表が変更される場合、トランザクションは表ロック(TMロック)を自動的に取得します。これらのDML操作が表ロックを必要とするのは、トランザクションのために表へのDMLアクセスを確保すること、およびトランザクションと競合する可能性のあるDDL操作を防止するという2つの目的のためです。表ロックは、LOCK TABLE文(「手動データ・ロック」を参照)を使用して明示的に取得できます。

表ロックは、次のいずれかのモードで保持できます。

  • 行共有ロック(RS)(半共有表ロック、SSとも呼ぶ): 表のロックを保持しているトランザクションがその表の行をロックしており、それらの行を更新する予定であることを示します。SSロックは最も制限の少ないモードの表ロックであり、表に対する同時実行性が最も高くなります。

  • 行排他ロック(RX)(副排他表ロック、SXとも呼ぶ): ロックを保持しているトランザクションが表の行を更新したか、SELECT ... FOR UPDATEを発行したことを示します。SXロックでは、他のトランザクションが同じ表の行に対して問合せ、挿入、更新、削除またはロックを実行できます。このため、SXロックの場合は、同じ表に対して同時に行われているSXロックとSSロックを複数のトランザクションで取得できます。

  • 共有表ロック(S): トランザクションが共有表ロックを保持している場合は、(SELECT ... FOR UPDATEを使用することなく)他のトランザクションによる同じ表への問合せが許可されます。ただし、表を更新できるのは、1つのトランザクションが共有表ロックを保持する場合のみです。共有表ロックは、複数のトランザクションで同時に保持されている場合があるため、このロックを保持していても、トランザクションで常に表を変更できるとはかぎりません。

  • 共有行排他表ロック(SRX)(共有副排他表ロック、SSXとも呼ぶ): 共有表ロックよりも制限の厳しいロックです。特定の表に対して、同時に1つのトランザクションのみがSSXロックを取得できます。トランザクションがSSXロックを保持している場合、他のトランザクションは表への問合せが許可されます(SELECT ... FOR UPDATEの場合を除く)。ただし、表の更新は許可されません。

  • 排他表ロック(X): 最も制限の厳しいモードの表ロックです。このロックを保持しているトランザクションには、表への排他的な書込みアクセスが許可されます。表のXロックを取得できるのは、1つのトランザクションのみです。

関連項目:

手動データ・ロック

DML操作でのロック

Oracle Databaseでは、DML操作を実行すると行レベルと表レベルのロックが自動的に取得されます。ロック動作は操作の種類によって決まります。表B-1は、この項の情報をまとめたものです。

ノート:

表B-1のDML文に示されている暗黙のSXロックは、制約の影響により一時的に排他(X)ロックになることがあります。

表B-1 DML文で取得されるロックのまとめ

SQL文 行ロック 表ロック・モード RS RX S SRX X

SELECT ... FROM table...

なし

INSERT INTO table ...

SX

不可

不可

不可

UPDATE table ...

SX

脚注 1

脚注 1

不可

不可

不可

MERGE INTO table ...

SX

不可

不可

不可

DELETE FROM table ...

SX

脚注 1

脚注 1

不可

不可

不可

SELECT ... FROM table FOR UPDATE OF ...

SX

脚注 1

脚注 1

不可

不可

不可

LOCK TABLE table IN ...

   ROW SHARE MODE

SS

不可

   ROW EXCLUSIVE MODE

SX

不可

不可

不可

   SHARE MODE

S

不可

不可

不可

   SHARE ROW EXCLUSIVE MODE

SSX

不可

不可

不可

不可

   EXCLUSIVE MODE

X

不可

不可

不可

不可

不可

脚注1

競合する行ロックが別のトランザクションによって保持されていない場合には、可。それ以外の場合は待機します。

行を問い合せるときのロック

問合せは、SELECT文の場合のように明示的に行われることも、ほとんどのINSERTMERGEUPDATEおよびDELETE文の場合のように暗黙的に行われることもあります。問合せコンポーネントを含まなくてもかまわない唯一のDML文は、VALUES句を伴うINSERT文です。問合せはデータを読み取るのみであるため、他のSQL文に対してほとんど干渉しないSQL文です。

次の特性は、FOR UPDATE句を伴わない問合せが該当します。

  • 問合せはデータ・ロックを取得しません。そのため、特定の行に対して問合せが実行される場合も含め、問合せが実行されている表を、他のトランザクションが問い合せて更新できます。FOR UPDATE句を伴わない問合せでは、他の操作をブロックするデータ・ロックが取得されないため、このような問合せを非ブロック問合せと呼ぶことがあります。

  • 問合せでは、データ・ロックが解除されるまで待機する必要はありません。そのため、問合せはいつでも実行できます。このルールの例外としては、分散トランザクションが保留中であるなど、きわめて特殊な場合にデータ・ロックの待機が必要になることがあります。

行を変更するときのロック

一部のデータベースでは、ロック・マネージャを使用してメモリー内のロック・リストをメンテナンスします。一方、Oracle Databaseでは、ロックされている行を含むデータ・ブロックにロック情報を格納します。各行ロックが影響するのは1つの行のみです。

Oracle Databaseでは、キューイング・メカニズムを使用して行ロックを取得します。行ロックを必要とするトランザクションは、まだ行がロックされていなければ、行のデータ・ブロックにロックを取得します。トランザクション自体は、ブロック・ヘッダーの対象トランザクション・リスト(ITL)・セクションにエントリが記録されます。このトランザクションで変更されるそれぞれの行は、ITLに格納されたトランザクションIDのコピーをポイントします。したがって、同じブロックに含まれる100行を1つのトランザクションで変更する場合は100個の行ロックが必要ですが、100行すべてが1つのトランザクションIDを参照します。

トランザクションが終了すると、トランザクションIDはデータ・ブロック・ヘッダーのITLセクションにそのまま残ります。新しいトランザクションで行の変更が必要になると、ロックがアクティブかどうかの判断は、そのトランザクションIDを使用して行われます。ロックがアクティブな場合、新しいトランザクションのセッションは、ロックが解除されたときの通知を要求します。アクティブでない場合は、新しいトランザクションがロックを取得します。

INSERTUPDATEDELETEおよびSELECT ... FOR UPDATE文の特性は次のとおりです。

  • DML文を含むトランザクションは、その文の変更対象の行に対して行排他ロックを取得します。そのため、行をロックしているトランザクションがコミットまたはロールバックされるまで、他のトランザクションは、ロックされている行を更新したり削除することはできません。

  • これらの行ロックに加え、データを変更するDML文を含むトランザクションは、変更対象の行を含む表に対して副排他表ロック(SX)以上のロックを取得することも必要です。その表に対してトランザクションが、S、SRXまたはX表ロック(SXロックよりも制限が厳しいロック)をすでに保持している場合、SXロックは不要であるため取得しません。ただし、このトランザクションがSSロックのみをすでに保持している場合、Oracle DatabaseはSSロックをSXロックに自動的に変換します。

  • DML文を含むトランザクションは、副問合せや暗黙的な問合せによって選択される行に対して行ロックを取得する必要はありません。

    次のUPDATE文の例では、カッコ内のSELECT文が副問合せであり、WHERE a > 5句が暗黙的な問合せです。

    UPDATE t SET x = ( SELECT y FROM t2 WHERE t2.z = t.z ) WHERE a > 5;
    

    DML文内にある副問合せや暗黙的な問合せは、問合せの開始時点での一貫性が保証されており、その問合せで構成されているDML文による影響を参照しません。

  • トランザクション内の問合せは、同じトランザクション内の前のDML文で行われた変更を参照できますが、他のトランザクションのコミットされていない変更は参照できません。

関連項目:

外部キーのロックの詳細は、『Oracle Database概要』を参照してください。