Зачем нужны блокировки в базе данных
Что проверяют
Понимаете ли вы, что база сама решает конфликты параллельных транзакций, и знаете ли, где нужна явная блокировка.
Как отвечать
Блокировки нужны, чтобы параллельные транзакции не портили данные друг друга: не терялись обновления, не читалось промежуточное состояние, не менялся результат внутри одной транзакции.
Важно сразу сказать про модель PostgreSQL: там используется многоверсионность, поэтому читатели не блокируют писателей, а писатели не блокируют читателей. Чтение видит согласованный снимок данных, и явные блокировки нужны заметно реже, чем кажется.
Что бывает:
- блокировки строк при
UPDATEиDELETE, а также явные черезSELECT ... FOR UPDATE. Нужны для схемы «прочитал, посчитал, записал», где иначе две транзакции затрут работу друг друга; - блокировки таблиц при изменении структуры:
ALTER TABLEможет остановить всё обращение к таблице, поэтому на больших таблицах миграции делают осторожно; - рекомендательные блокировки (
pg_advisory_lock) для координации на уровне приложения, например чтобы фоновая задача выполнялась в одном экземпляре; - оптимистичная схема без блокировок: колонка версии, обновление с условием на неё, и при конфликте повтор. Хорошо работает при редких конфликтах.
Обязательно назовите риски: взаимные блокировки при разном порядке захвата (лечится единым порядком), длинные транзакции, которые держат блокировки и мешают всем, и очередь ожидающих, которая выглядит как «база тормозит», хотя проблема в удерживаемой блокировке.
Где спотыкаются
Берут блокировку и делают внутри транзакции внешний вызов, растягивая её на секунды.
Считают, что уровень изоляции решает всё сам: read committed не защищает от потерянного обновления в схеме «прочитал и записал».
Не смотрят на текущие блокировки при разборе тормозов, хотя в базе есть представления, которые прямо показывают, кто кого ждёт.