Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Warum einen TSQL-Anweisungsblock einfügen, wenn die Transaktionsisolationsebene für eine andere Transaktion mit einem konfliktfreien Filter serialisierbar ist?

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')