Механизмы управления конкурентным доступом к данным в RDBMS
- Механизмы управления конкурентным доступом в rdbms
- Mvcc в postgresql
- Уровни изоляции транзакций в базах данных
- Select for update блокировка записей
- Advisory locks
- Предикативные блокировки
- Vacuum процесс
1. MVCC – Multi-Version Concurrency Control
Это дефолтный механизм в различных RDBMS, включая Postgres. При выполнении UPDATE/DELETE операций вместо overwrite создается новая версия записи. Старые данные помечаются как “DEAD”, и будут удалены операцией VACUUM.
VACUMM может быть вызван как вручную, так и автоматически (AUTOVACUUM). Удаление “DEAD” данных происходит когда все активные транзакции перестают видеть старые версии.
MVCC разруливает проблемы многопоточного доступа на базовом уровне:
- Запись не блокируется читателями; вместо этого создается новая версия данных
- В момент операции записи, читатели видят снапшот предыдущих данных.
При этом это происходит без блокировок для чтения, но изменения могут блокировать друг друга. В таком случае поведение будет зависеть уже от уровня изоляции транзакций.
2. Transactions
Некоторые задачи координации доступа к данным можно эффективно решить с помощью транзакций и настройки уровня изоляции тразнаций:
- Read Committed
- Repeatable Read
- Serializable
3. select for update
Конструкция “select for update” – взятие лока на конкретные записи уровне БД. Лок будет взят сразу после выполнения этой конструкции, а отпущен в момент COMMIT и ROLLBACK транзации.
Особенность конструкции в том, что это не предикативная блокировка, т.е. невозможно заблокировать запись, которой еще нет.
4. Advisory locks
Наиболее гибкий вариант – клиент БД должен сам взять лок по конкретному числу int. Идентификатор может быть любым числом, не обязательно существующим id записи, хотя это один из вариантов.
Выглядит это так:
SELECT pg_advisory_xact_lock(42); -- Блокировка на время текущей транзакции
Также есть вариант взять лок на время сессии.
Другими словами – мы взяли лок с id=42. Если другой поток попытается взять лок с id=43 – это произойдет сразу, но если с id=42 – то потребуется, чтобы изначальная транзакция завершилась.