Настройка теста
У меня есть SQL Server 2014 и простая таблица MyTable
, которая содержит столбцы Code (int)
и Data (nvarchar(50))
, индексы для этой таблицы не созданы.
У меня есть 4 записи в таблице следующим образом:
1, First
2, Second
3, Third
4, Fourth
Затем я выполняю следующий запрос в транзакции:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRANSACTION
DELETE FROM dbo.MyTable
WHERE dbo.MyTable.Code = 2
У меня есть одна затронутая row и я не выдаю Commit или Rollback.
Далее я запускаю еще одну транзакцию:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT TOP 10 Code, Data
FROM dbo.MyTable
WHERE Code = 3
На этом шаге транзакция с запросом SELECT зависает в ожидании завершения транзакции. с запросом DELETE.
Мой вопрос
Я не понимаю, почему транзакция с запросом SELECT ожидает транзакцию с запросом DELETE. В моем понимании удаленная строка (с кодом 2) не имеет ничего общего с выбранной строкой (с кодом 3), и, насколько я понимаю, спецификация c уровня изоляции SERIALIZABLE SQL Сервер не должен блокировать всю таблицу в этот случай. Может быть, это происходит потому, что минимальная блокировка для SERIALIZABLE - это страница? Тогда это может привести к непоследовательному поведению при выборе строк на некоторых других страницах, если в таблице будет больше строк, например, 1000000 (некоторые строки с других страниц не будут заблокированы). Пожалуйста, помогите выяснить, почему блокировка происходит в моем случае.