ロック モード

Microsoft SQL Server データベース エンジンは、さまざまなロック モードを使用してリソースをロックします。これにより、同時に実行されている複数のトランザクションがリソースにアクセスする方法が決まります。

適用対象: SQL Server 2008 R2 以上のバージョン。

次の表に、データベース エンジンのリソース ロック モードを示します。

ロック モード

説明

共有 (S)

SELECT ステートメントなど、データの変更や更新を伴わない読み取り操作で使用します。

更新 (U)

更新可能なリソースに使用します。複数のセッションがリソースを読み取り、ロックして、後で更新する可能性がある場合に発生する一般的な形式のデッドロックを防ぎます。

排他 (X)

INSERT、UPDATE、DELETE などのデータ変更操作に使用します。複数の更新操作により 1 つのリソースを同時に更新しないようにするためのロック モードです。

インテント

ロック階層を設定するのに使用します。インテント ロックには、インテント共有 (IS)、インテント排他 (IX)、およびインテント排他付き共有 (SIX) があります。

スキーマ

テーブルのスキーマに依存する操作を行うときに使用します。スキーマ ロックには、スキーマ修正 (Sch-M) およびスキーマ安定度 (Sch-S) があります。

一括更新 (BU)

データを一括でテーブルにコピーするときに TABLOCK ヒントを指定して使用します。

キー範囲

トランザクション分離レベルが SERIALIZABLE のとき、クエリにより読み取られる行の範囲を保護します。シリアル化可能トランザクションのクエリを再度実行した場合に対象となるような行を、他のトランザクションは挿入できなくなります。

共有ロック

共有 (S) ロックを設定すると、同時に実行されている複数のトランザクションがペシミスティック同時実行制御の下でリソースの読み取り (SELECT) を行います。詳細については、「同時実行制御の種類」を参照してください。他のトランザクションは、リソースに共有 (S) ロックがかけられている間はデータを変更できません。リソースにかけられている共有 (S) ロックは、読み取りが完了するとすぐに解除されます。ただし、トランザクションの分離レベルが REPEATABLE READ 以上に設定されている場合や、トランザクションの間、ロック ヒントを使用して共有 (S) ロックを保つ場合を除きます。

更新ロック

更新 (U) ロックは、一般的な形式のデッドロックを防ぎます。REPEATABLE READ または SERIALIZABLE のトランザクションは、データを読み取るときにリソース (ページまたは行) に共有 (S) ロックをかけます。その後、行を変更しますが、そのときにロックを排他 (X) ロックに変換する必要があります。2 つのトランザクションが 1 つのリソースに対して共有ロックをかけデータを同時に更新する場合、一方のトランザクションは排他 (X) ロックへの変換を試みます。一方のトランザクションの排他ロックは、もう一方のトランザクションの共有ロックとは両立しないので、共有ロックから排他ロックへの変換が待機状態になります。つまり、ロック待機となります。もう一方のトランザクションも更新のために排他 (X) ロックの取得を試みます。この場合、2 つのトランザクションが排他 (X) ロックへの変換を行っており、相手方のトランザクションが共有ロックを解除するのを待っている状態なので、デッドロックが発生します。

このような潜在的なデッドロックの問題を解決するには、更新 (U) ロックを使用します。更新 (U) ロックでは、1 つのリソースを一度にロックできるトランザクションは、1 つだけです。トランザクションがリソースを変更する場合に更新 (U) ロックが排他 (X) ロックに変換されます。

排他ロック

排他 (X) ロックは、同時に実行されている複数のトランザクションが同じリソースにアクセスすることを防ぎます。排他 (X) ロックをかけた以外のトランザクションはデータを変更できませんが、NOLOCK ヒントまたは READ UNCOMMITTED 分離レベルが指定されている場合に限り、読み取り操作は行うことができます。

INSERT、UPDATE、DELETE などのデータ変更ステートメントの中では、変更操作と読み取り操作が組み合わせて使用されます。最初に読み取り操作でデータを取得してから、必要な変更操作を実行します。したがって、一般的にデータ変更ステートメントには共有ロックおよび排他ロックの両方が必要です。たとえば、UPDATE ステートメントによって、他のテーブルとの結合を基にテーブルの行を変更するとします。このとき、結合テーブルの読み取る行に対する共有ロックと、更新する行に対する排他ロックが要求されます。

インテント ロック

データベース エンジンではインテント ロックを使用して、下位のロック階層に位置するリソースに共有 (S) ロックまたは排他 (X) ロックがかかるのを保護します。インテント ロックの命名の由来は、ロックのタイミングが下位レベルのロックよりも前であり、下位レベルでロックをかける意図 (intent) を示すためです。

インテント ロックの用途は次の 2 つです。

  • 他のトランザクションが上位のリソースを変更することにより下位レベルのロックを無効にしてしまうことを防ぐ。

  • データベース エンジンによって高い粒度でロックの競合を検出する効率を向上する。

たとえば、あるテーブルのページまたは行の共有 (S) ロックを要求する前に、テーブル レベルの共有インテント ロックを要求するとします。テーブル レベルのインテント ロックを設定すると、それ以降、別のトランザクションによってそのページを含むテーブルに排他 (X) ロックがかけられる状態を回避することができます。インテント ロックを使用すればパフォーマンスが向上します。データベース エンジンでは、トランザクションがテーブルに対して安全にロックをかけることができるかどうかを判断する際に、テーブル レベルのインテント ロックを調べるだけで済みます。これにより、トランザクションがテーブル全体をロックできるかどうかを判断するために、テーブルの各行や各ページのロックを調べる必要がなくなります。

インテント ロックにはインテント共有 (IS)、インテント排他 (IX)、およびインテント排他付き共有 (SIX) があります。

ロック モード

説明

インテント共有 (IS)

下位の階層に位置するリソースの (すべてではなく) 一部に対し、要求されているかかけられている共有ロックを保護します。

インテント排他 (IX)

下位の階層に位置するリソースの (すべてではなく) 一部に対し、要求されているかかけられている排他ロックを保護します。IX は IS のスーパーセットです。また、下位のリソースに対する共有ロックの要求を保護します。

インテント排他付き共有 (SIX)

下位の階層に位置するすべてのリソースに対し、要求されているかかけられている共有ロックを保護し、下位のリソースの (すべてではなく) 一部のインテント排他ロックを保護します。上位リソースで同時実行している IS ロックは可能です。たとえば、テーブルに対し SIX ロックをかけると、変更中のページにインテント排他ロックが、変更中の行に排他ロックがかかります。1 つのリソースに対しては、一度に 1 つの SIX ロックしかかけられません。その結果、他のトランザクションによってリソースが更新されることはなくなりますが、他のトランザクションはテーブル レベルの IS ロックをかけることで下位のリソースを読み取ることができます。

インテント更新 (IU)

下位の階層に位置するすべてのリソースに対し、要求されているかかけられている更新ロックを保護します。IU ロックはページ リソースに対してのみ使用します。更新操作が発生すると、IU ロックは IX ロックに変換されます。

共有インテント更新 (SIU)

S ロックと IU ロックを個別にかけるか、同時にかけるかして組み合わせたものです。たとえば、トランザクションで PAGLOCK ヒントを指定してクエリを実行してから更新操作を実行するとします。PAGLOCK ヒントを指定したクエリで S ロックをかけ、更新操作で IU ロックをかけます。

更新インテント排他 (UIX)

U ロックと IX ロックを個別にかけるか、同時にかけるかして組み合わせたものです。

スキーマ ロック

データベース エンジンは、テーブルにデータ定義言語 (DDL) 操作 (列の追加やテーブルの削除など) を行うときにスキーマ修正 (Sch-M) ロックを使用します。ロックが保持されている場合、Sch-M ロックはテーブルへの同時アクセスを防ぎます。つまり、Sch-M ロックは、ロックが解除されるまで外部からの操作をすべてブロックします。

テーブルの切り捨てなど一部のデータ操作言語 (DML) 操作では、同時操作によって影響を受けるテーブルへのアクセスを防ぐために Sch-M ロックを使用します。

データベース エンジンは、クエリをコンパイルして実行する際にスキーマ安定度 (Sch-S) ロックを使用します。Sch-S ロックは、排他 (X) ロックを含めて、どのトランザクション ロックもブロックしません。したがって、その他のトランザクション (テーブルを X ロックするトランザクションなど) は、クエリのコンパイル中も継続して実行されます。ただし、Sch-M ロックを取得する DDL 同時操作や DML 同時操作をテーブルに対して実行することはできません。

一括更新ロック

データベース エンジンは、データをテーブルに一括コピーする際に一括更新 (BU) ロックを使用します。一括更新ロックは、TABLOCK ヒントを指定するか、または sp_tableoption を使用して table lock on bulk load テーブル オプションを指定した場合に使用されます。一括更新 (BU) ロックをかけると、同時に複数のスレッドによりデータを同一のテーブルに一括で読み込むことができますが、一括読み込みに参加していない他のプロセスは、その間テーブルにアクセスできません。

キー範囲ロック

キー範囲ロックは、SERIALIZABLE トランザクション分離レベルの状態で、Transact-SQL ステートメントで読み取っているレコード セットに含まれている行の範囲を暗黙的に保護します。キー範囲ロックをかけると、ファントム読み取りを回避できます。行間のキー範囲を保護することで、トランザクションからアクセスするレコード セットへのファントム挿入やファントム削除も回避されます。