Het eerste probleem in uw testscenario is dat de tabel geen bruikbare index heeft op firstname
. De tweede is dat de tafel leeg is.
Van Toetsenbereikvergrendeling in BOL
Er is geen geschikte index om RangeS-S
te nemen vergrendelt dus om serialiseerbare semantiek te garanderen, moet SQL Server de hele tabel vergrendelen.
Als u probeert een geclusterde index toe te voegen aan de tabel in de kolom met de voornaam, zoals hieronder, en het experiment herhaalt ...
CREATE CLUSTERED INDEX [IX_FirstName] ON [dbo].[dummy] ([firstname] ASC)
... je zult merken dat je nog steeds geblokkeerd bent!
Ondanks het feit dat er nu een geschikte index bestaat en het uitvoeringsplan laat zien dat er naar wordt gezocht om aan de vraag te voldoen.
U kunt zien waarom door het volgende uit te voeren
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
Retourneren
+---------------+----------------------+--------------+
| resource_type | resource_description | request_mode |
+---------------+----------------------+--------------+
| DATABASE | | S |
| OBJECT | | IS |
| PAGE | 1:198 | IS |
| KEY | (ffffffffffff) | RangeS-S |
+---------------+----------------------+--------------+
SQL Server verwijdert niet zomaar een bereikvergrendeling op precies het bereik dat u opgeeft in uw zoekopdracht.
Voor een gelijkheidspredikaat op een unieke index, als er een overeenkomende sleutel is, is er gewoon een normaal slot nodig in plaats van welk type bereikslot dan ook.
Voor een niet-uniek zoekpredikaat verwijdert het sloten op alle overeenkomende sleutels binnen het bereik plus de "volgende" aan het einde van het bereik (of op ffffffffffff
om oneindigheid weer te geven als er geen "volgende" sleutel bestaat). Zelfs verwijderde "ghost"-records
kan worden gebruikt in dit bereik sleutelvergrendeling.
Zoals hier beschreven voor een gelijkheidspredikaat op een unieke of niet-unieke index
Dus met een lege tabel de SELECT
eindigt nog steeds met het vergrendelen van de hele index. U moet ook eerder een rij hebben ingevoegd tussen abc
en lmn
en dan zou je invoeging slagen.
insert into dummy values('def', 'def')