私と私の同僚は、シリアル化可能な分離レベルの使用の影響について説明しました。彼はそれがテーブル全体をロックしたと言ったが、私は彼にそれが潜在的に可能であると伝えることに同意しなかったが、それは範囲ロックを適用しようとし、ここで説明されるように真のシリアライゼーションを適用しない: The Serializable Isolation Level 。
「テーブル全体をロックする」のドキュメントでも何も見つかりません: SET TRANSACTION ISOLATION LEVEL 。
ドキュメントには範囲ロックに関する多くの事項が記載されているため、理論的には、テーブル内の可能な値の範囲全体をロックする範囲ロックを持つだけでテーブル全体をロックできますが、テーブルはロックされません。
私はここで完全に間違っていますか?実際には、テーブル全体をロックしていますか?
Lock escalation シリアライズ可能な分離レベルでは、他の分離レベルと同じように発生する可能性があります。
単一のインデックスを持つ単一のテーブルを使用したいくつかの簡単な例。 Idは、テーブルの主キーおよびクラスター化インデックスです。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
UPDATE c
SET c.Score = 2147483647
FROM dbo.Comments AS c
WHERE c.Id = 138; --One value
ROLLBACK
単一のID値の場合、ロックは最小限です。
+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| RangeX-X | Comments | KEY | 1 |
| IX | Comments | OBJECT | 1 |
| IX | Comments | PAGE | 1 |
+--------------+---------------+---------------+-------------+
しかし、範囲内で作業を開始すると、ロックが上がります。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
UPDATE c
SET c.Score = 2147483647
FROM dbo.Comments AS c
WHERE c.Id BETWEEN 1 AND 5000; -- Small range
ROLLBACK
これで、より多くのキーにさらに排他ロックが設定されました。
+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| RangeX-X | Comments | KEY | 2429 |
| IX | Comments | OBJECT | 1 |
| IX | Comments | PAGE | 97 |
+--------------+---------------+---------------+-------------+
これは、転換点に達するまで続きます。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
UPDATE c
SET c.Score = 2147483647
FROM dbo.Comments AS c
WHERE c.Id BETWEEN 1 AND 11655; --Larger range
ROLLBACK
ロックのエスカレーションが試行され、成功しました:
+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| X | Comments | OBJECT | 1 |
+--------------+---------------+---------------+-------------+
ここで2つの概念を分離することが重要です。どのレベルのロックが取得されても、分離レベルはシリアル化可能です。クエリは分離レベルを選択し、ストレージエンジンはロックを選択します。シリアライズ可能が常に範囲ロックになるとは限りません。ストレージエンジンは、分離レベルを維持するロックの種類を選択できます。
検索述語にインデックスがある場合、それは範囲ロックに使用される可能性があります。
つまり、範囲内の最初の行から次の行にロックします。そして、その次から3行目まで、というように。範囲の最後の行まで。したがって、本質的にはいくつかの行ロックですが、「中間」値の挿入から範囲をブロックします(範囲をロックします)。
これを実現するには、(SQL Server)で使用するインデックスが必要です。ロックインを行うためのインデックス(述語のインデックス)がなければ、(私が知っていることから)テーブルロックが取得されます。