Das erste Problem in Ihrem Testszenario ist, dass die Tabelle keinen nützlichen Index für firstname
hat . Die zweite ist, dass die Tabelle leer ist.
Von Schlüsselbereichssperre im BOL
Es gibt keinen geeigneten Index, um RangeS-S
zu nehmen sperrt, um eine serialisierbare Semantik zu gewährleisten, muss SQL Server die gesamte Tabelle sperren.
Wenn Sie versuchen, einen gruppierten Index in der Tabelle in der Vornamensspalte wie unten hinzuzufügen, und das Experiment wiederholen ...
CREATE CLUSTERED INDEX [IX_FirstName] ON [dbo].[dummy] ([firstname] ASC)
... Sie werden feststellen, dass Sie immer noch blockiert sind!
Trotz der Tatsache, dass jetzt ein geeigneter Index existiert und der Ausführungsplan zeigt, dass er gesucht wird, um die Abfrage zu erfüllen.
Sie können sehen, warum, indem Sie Folgendes ausführen
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT *
FROM dummy
WHERE firstname = 'abc'
SELECT resource_type,
resource_description,
request_mode
FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID
COMMIT
Rückgabe
+---------------+----------------------+--------------+
| resource_type | resource_description | request_mode |
+---------------+----------------------+--------------+
| DATABASE | | S |
| OBJECT | | IS |
| PAGE | 1:198 | IS |
| KEY | (ffffffffffff) | RangeS-S |
+---------------+----------------------+--------------+
SQL Server führt nicht nur eine Bereichssperre für genau den Bereich aus, den Sie in Ihrer Abfrage angeben.
Für ein Gleichheitsprädikat auf einem eindeutigen Index wird, wenn es einen passenden Schlüssel gibt, nur eine normale Sperre statt irgendeiner Art von Bereichssperre verwendet.
Für ein nicht eindeutiges Suchprädikat werden alle übereinstimmenden Schlüssel innerhalb des Bereichs plus der "nächste" am Ende des Bereichs (oder auf ffffffffffff
) gesperrt um Unendlich darzustellen, wenn keine "Weiter"-Taste existiert). Sogar gelöschte "Geister"-Einträge
kann in diesem Bereich Tastensperre verwendet werden.
Wie hier beschrieben für ein Gleichheitsprädikat für einen eindeutigen oder nicht eindeutigen Index
Also bei einer leeren Tabelle das SELECT
endet immer noch mit dem Sperren des gesamten Index. Außerdem müssten Sie zuvor eine Zeile zwischen abc
eingefügt haben und lmn
und dann würde Ihre Einfügung erfolgreich sein.
insert into dummy values('def', 'def')