advanced

Locks

Рассуждайте о row, table, predicate, optimistic и advisory locks как инструментах защиты concurrent work.

Locks сериализуют доступ к строкам, страницам или таблицам, чтобы параллельные транзакции не испортили общее состояние. Движки сочетают MVCC-чтение с явными или неявными write locks.

| Механизм | Поведение | |----------|-----------| | Row-level write lock | Блокирует конфликтующие update той же строки | | `SELECT ... FOR UPDATE` | Pessimistic: lock строк до update | | `SELECT ... FOR SHARE` | Shared lock — блокирует writers, пропускает readers | | Predicate / gap lock | Защищает диапазоны — от phantoms (InnoDB) | | Table lock | Грубый — миграции, bulk DDL | | Advisory lock | Mutex приложения (`pg_advisory_lock`) | | Optimistic concurrency | Столбец version — retry при `UPDATE ... WHERE version = ?` |

					BEGIN;
SELECT * FROM seats WHERE flight_id = 42 AND seat_no = '12A'
  FOR UPDATE;
-- приложение проверяет status, затем update
UPDATE seats SET status = 'sold' WHERE id = 991;
COMMIT;
				

Deadlock возникает, когда две tx ждут locks друг друга — движок прерывает жертву; приложение должно повторять с backoff. Упорядочивание locks (сначала родитель, потом ребёнок) снижает циклы.

На интервью: сравните pessimistic row locks и optimistic versioning для бронирования места или складского счётчика.

Типовые ошибки: `FOR UPDATE` на широком scan, блокирующий тысячи строк; отсутствие индекса превращает row locks в gap/table locks; длинные транзакции с locks; advisory locks без timeout и fencing.

Компромисс — между эксклюзивным доступом ради корректности и пропускной способностью / риском deadlock: блокируйте минимальную гранularity на минимальное время, сохраняющее инвариант.

Чеклист:

  • Назовите защищаемый ресурс и гранularity.
  • Выберите pessimistic vs optimistic под паттерн contention.
  • Задайте порядок locks против deadlocks.
  • Запланируйте retry при deadlock или serialization failure.
  • Замеряйте lock wait time в production-метриках.