Что такое эскалация блокировок (lock escalation) в базе данных и как она работает
Что проверяют
Понимаете ли вы, что гранулярность блокировок это компромисс: мелкие дают параллелизм, но стоят памяти и учёта. И, что важнее для джависта, знаете ли вы, что эскалация свойство конкретной СУБД, а не общий закон, и умеете ли смотреть на транзакции приложения с этой стороны.
Как отвечать
Менеджер блокировок держит каждую взятую блокировку в памяти. Когда одна инструкция набирает их слишком много, часть СУБД заменяет пачку строковых блокировок одной крупной. В SQL Server порог задан числом блокировок на инструкцию и давлением на память, переход идёт сразу на таблицу, при настройке на секцию. DB2 ведёт себя похоже. В PostgreSQL и Oracle эскалации блокировок строк нет вовсе: признак блокировки хранится в самой строке, и миллион заблокированных строк не стоит менеджеру ничего. В PostgreSQL укрупняются предикатные блокировки сериализуемых транзакций, но это про ложные конфликты сериализации, а не про ожидание записи.
Практический вывод для приложения: чем длиннее транзакция и чем шире выборка под изменение, тем выше цена. Массовое обновление через ORM разбивают на пачки с фиксацией между ними, порядок обработки делают одинаковым во всех местах кода, пессимистичную блокировку ставят на минимальный набор строк и на минимальное время.
Где спотыкаются
Отвечают так, будто механизм есть у всех, и на уточнение про PostgreSQL продолжают рассказывать про переход на уровень таблицы. Сильный ответ начинается со слов «зависит от СУБД» и дальше разбирает пару конкретных.
Описывают лестницу из строки, страницы и таблицы как обязательные ступени. На практике переход обычно одноступенчатый, а сама попытка может не удаться, если мешают чужие блокировки, и тогда движок повторит её позже.
Лечат симптом: поднимают таймаут, снижают уровень изоляции, добавляют подсказки оптимизатору. Причина почти всегда в том, что транзакция трогает лишние строки или живёт слишком долго; подходящий индекс и разбиение на пачки снимают проблему без настроек движка.