První problém ve vašem testovacím scénáři je, že tabulka nemá žádný užitečný index na firstname
. Druhým je, že tabulka je prázdná.
Z Key-Range Locking v BOL
Neexistuje žádný vhodný index pro RangeS-S
uzamkne, aby byla zaručena serializovatelná sémantika, kterou SQL Server potřebuje k uzamčení celé tabulky.
Pokud se pokusíte přidat seskupený index do tabulky do sloupce křestního jména, jak je uvedeno níže, a zopakujte experiment ...
CREATE CLUSTERED INDEX [IX_FirstName] ON [dbo].[dummy] ([firstname] ASC)
... zjistíte, že jste stále blokováni!
Navzdory skutečnosti, že vhodný index nyní existuje a prováděcí plán ukazuje, že se hledá, aby byl dotaz splněn.
Důvod můžete zjistit spuštěním následujícího
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
Vrátí
+---------------+----------------------+--------------+
| resource_type | resource_description | request_mode |
+---------------+----------------------+--------------+
| DATABASE | | S |
| OBJECT | | IS |
| PAGE | 1:198 | IS |
| KEY | (ffffffffffff) | RangeS-S |
+---------------+----------------------+--------------+
SQL Server nevyjímá pouze zámek rozsahu přesně pro rozsah, který zadáte ve svém dotazu.
Pro predikát rovnosti na jedinečném indexu, pokud existuje odpovídající klíč, bude zapotřebí pouze běžný zámek, nikoli jakýkoli typ zámku rozsahu.
Pro nejedinečný predikát hledání odstraní zámky na všech odpovídajících klíčích v rozsahu plus "další" na konci rozsahu (nebo na ffffffffffff
reprezentovat nekonečno, pokud neexistuje žádný „další“ klíč). Dokonce i smazané „ghost“ záznamy
lze v tomto rozsahu použít zamykání klíčem.
Jak je popsáno zde pro predikát rovnosti na jedinečném nebo nejedinečném indexu
Takže s prázdnou tabulkou SELECT
stejně skončí uzamčením celého indexu. Také byste museli předtím vložit řádek mezi abc
a lmn
a pak by vaše vložka byla úspěšná.
insert into dummy values('def', 'def')