web-dev-qa-db-ja.com

SQL Serverのシリアル化可能な分離レベルはテーブル全体をロックしますか

私と私の同僚は、シリアル化可能な分離レベルの使用の影響について説明しました。彼はそれがテーブル全体をロックしたと言ったが、私は彼にそれが潜在的に可能であると伝えることに同意しなかったが、それは範囲ロックを適用しようとし、ここで説明されるように真のシリアライゼーションを適用しない: The Serializable Isolation Level

「テーブル全体をロックする」のドキュメントでも何も見つかりません: SET TRANSACTION ISOLATION LEVEL

ドキュメントには範囲ロックに関する多くの事項が記載されているため、理論的には、テーブル内の可能な値の範囲全体をロックする範囲ロックを持つだけでテーブル全体をロックできますが、テーブルはロックされません。

私はここで完全に間違っていますか?実際には、テーブル全体をロックしていますか?

9
mslot

ただし、エスカレーション

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つの概念を分離することが重要です。どのレベルのロックが取得されても、分離レベルはシリアル化可能です。クエリは分離レベルを選択し、ストレージエンジンはロックを選択します。シリアライズ可能が常に範囲ロックになるとは限りません。ストレージエンジンは、分離レベルを維持するロックの種類を選択できます。

16
Erik Darling

検索述語にインデックスがある場合、それは範囲ロックに使用される可能性があります。

つまり、範囲内の最初の行から次の行にロックします。そして、その次から3行目まで、というように。範囲の最後の行まで。したがって、本質的にはいくつかの行ロックですが、「中間」値の挿入から範囲をブロックします(範囲をロックします)。

これを実現するには、(SQL Server)で使用するインデックスが必要です。ロックインを行うためのインデックス(述語のインデックス)がなければ、(私が知っていることから)テーブルロックが取得されます。

5
Tibor Karaszi