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-метриках.