Эскалация блокировки — это механизм SQL Server, при котором множество блокировок мелкой гранулярности (например, на уровне строк) автоматически преобразуются в одну блокировку более крупной гранулярности (например, на уровне таблицы).
Исходное состояние:
-- Транзакция блокирует множество строк
UPDATE LargeTable SET Status = 'Processed' WHERE CreateDate < '2023-01-01'
Порог эскалации:
Результат эскалации:
-- Блокировки строк заменяются одной блокировкой таблицы
-- Теперь вся таблица заблокирована
Снижение нагрузки на менеджер блокировок:
Оптимизация производительности:
Снижение параллелизма:
-- После эскалации другие транзакции не могут читать таблицу
-- Даже если им нужны незатронутые строки
Увеличение вероятности деадлоков:
Неожиданное поведение:
ALTER TABLE Orders SET (LOCK_ESCALATION = DISABLE)
-- Или для отдельной транзакции
BEGIN TRAN
UPDATE Orders WITH (TABLOCKX) SET Status = 'Processed'
COMMIT
-- Авто (по умолчанию)
ALTER TABLE Orders SET (LOCK_ESCALATION = AUTO)
-- На уровень раздела (для партиционированных таблиц)
ALTER TABLE Orders SET (LOCK_ESCALATION = TABLE)
-- Вообще без эскалации
ALTER TABLE Orders SET (LOCK_ESCALATION = DISABLE)
-- Разбивка больших обновлений на пакеты
WHILE EXISTS (SELECT 1 FROM LargeTable WHERE Status = 'Pending')
BEGIN
UPDATE TOP (1000) LargeTable
SET Status = 'Processed'
WHERE Status = 'Pending'
END
Использование Extended Events:
CREATE EVENT SESSION [LockEscalation] ON SERVER
ADD EVENT sqlserver.lock_escalation
Анализ через DMV:
SELECT * FROM sys.dm_tran_locks
WHERE request_status = 'GRANT' AND resource_type = 'OBJECT'
Резюмируем: Эскалация блокировок — это компромисс между детализированным управлением параллельным доступом и производительностью системы. Понимание этого механизма позволяет разрабатывать более эффективные приложения и избегать проблем с блокировками в высоконагруженных системах. Для критически важных операций рекомендуется явно управлять эскалацией через настройки таблиц или подсказки блокировок.