Първият проблем във вашия тестов сценарий е, че таблицата няма полезен индекс на firstname
. Второто е, че таблицата е празна.
От Заключване на обхват на ключове в BOL
Няма подходящ индекс за приемане на RangeS-S
заключва, така че да гарантира семантика, която може да се сериализира, SQL Server трябва да заключи цялата таблица.
Ако опитате да добавите клъстериран индекс към таблицата в колоната с първо име, както е по-долу, и повторете експеримента...
CREATE CLUSTERED INDEX [IX_FirstName] ON [dbo].[dummy] ([firstname] ASC)
... ще откриете, че все още сте блокирани!
Въпреки факта, че вече съществува подходящ индекс и планът за изпълнение показва, че той се търси, за да удовлетвори заявката.
Можете да видите защо, като стартирате следното
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
Връща
+---------------+----------------------+--------------+
| resource_type | resource_description | request_mode |
+---------------+----------------------+--------------+
| DATABASE | | S |
| OBJECT | | IS |
| PAGE | 1:198 | IS |
| KEY | (ffffffffffff) | RangeS-S |
+---------------+----------------------+--------------+
SQL Server не просто премахва заключване на диапазона точно в диапазона, който сте посочили в заявката си.
За предикат за равенство на уникален индекс, ако има съвпадащ ключ, той просто ще отнеме обикновено заключване, а не какъвто и да е тип заключване на диапазон.
За неуникален предикат за търсене той премахва заключвания на всички съвпадащи ключове в диапазона плюс "следващия" в края на диапазона (или на ffffffffffff
за представяне на безкрайност, ако не съществува ключ "следващ"). Дори изтрити "призрачни" записи
може да се използва в този диапазон за заключване на ключ.
Както е описано тук за предикат за равенство на уникален или неуникален индекс
Така че с празна таблица SELECT
все пак в крайна сметка заключва целия индекс. Трябва също така преди това да сте вмъкнали ред между abc
и lmn
и тогава вашето вмъкване ще успее.
insert into dummy values('def', 'def')