Как в PostgreSQL добиваются сериализуемости
1️⃣ Как кратко ответить
В PostgreSQL сериализуемость достигается с помощью механизма сериализуемой изоляции транзакций, который использует алгоритм Serializable Snapshot Isolation (SSI). Этот алгоритм позволяет транзакциям работать с моментальными снимками данных, предотвращая аномалии, такие как фантомные чтения, и обеспечивая поведение, эквивалентное последовательному выполнению транзакций.
2️⃣ Подробное объяснение темы
Сериализуемость — это самый строгий уровень изоляции транзакций в системах управления базами данных (СУБД). Он гарантирует, что результат выполнения параллельных транзакций будет таким же, как если бы эти транзакции выполнялись последовательно, одна за другой. В PostgreSQL сериализуемость достигается с помощью алгоритма Serializable Snapshot Isolation (SSI).
Зачем нужна сериализуемость?
Сериализуемость необходима для обеспечения целостности данных в условиях конкурентного доступа. Без нее параллельные транзакции могут привести к аномалиям, таким как:
- Фантомные чтения: когда одна транзакция видит изменения, сделанные другой транзакцией, которые не должны быть видны.
- Неповторяющиеся чтения: когда одна транзакция видит разные данные при повторном чтении в рамках одной транзакции.
- Потерянные обновления: когда изменения, сделанные одной транзакцией, перезаписываются другой транзакцией.
Как работает Serializable Snapshot Isolation (SSI)?
SSI в PostgreSQL использует моментальные снимки данных для каждой транзакции. Это позволяет транзакциям работать с консистентным состоянием данных, существующим на момент их начала. Однако, в отличие от традиционного подхода блокировок, SSI отслеживает потенциальные конфликты между транзакциями и предотвращает их, если они могут привести к несериализуемым результатам.
Пример работы SSI
Рассмотрим две транзакции, которые выполняются параллельно:
- Транзакция A: Читает данные из таблицы и выполняет некоторые вычисления.
- Транзакция B: Вносит изменения в те же данные, которые читает транзакция A.
С помощью SSI PostgreSQL:
- Создает моментальный снимок данных для транзакции A на момент ее начала.
- Позволяет транзакции B вносить изменения, но отслеживает, какие данные были изменены.
- Если транзакция A пытается зафиксировать свои изменения, PostgreSQL проверяет, не возникло ли конфликтов с транзакцией B.
- Если конфликт обнаружен, транзакция A будет отклонена и должна быть повторена.
Пример кода
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- Транзакция A
SELECT balance FROM accounts WHERE account_id = 1;
-- Некоторая логика обработки данных
-- ...
-- Попытка зафиксировать изменения
COMMIT;
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- Транзакция B
UPDATE accounts SET balance = balance + 100 WHERE account_id = 1;
-- Попытка зафиксировать изменения
COMMIT;
- BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;: Начало транзакции с уровнем изоляции SERIALIZABLE, что означает использование SSI.
- SELECT balance FROM accounts WHERE account_id = 1;: Транзакция A читает баланс счета. PostgreSQL создает моментальный снимок данных на момент начала транзакции.
- UPDATE accounts SET balance = balance + 100 WHERE account_id = 1;: Транзакция B обновляет баланс. PostgreSQL отслеживает изменения.
- COMMIT;: Попытка зафиксировать изменения. Если транзакция A пытается зафиксировать изменения после транзакции B, PostgreSQL проверяет наличие конфликтов. Если конфликт обнаружен, транзакция A будет отклонена.
Заключение
Serializable Snapshot Isolation в PostgreSQL позволяет достичь сериализуемости без значительных накладных расходов на блокировки, обеспечивая при этом целостность данных и предотвращая аномалии, возникающие при параллельном выполнении транзакций. Это делает PostgreSQL мощным инструментом для работы с критически важными данными в условиях высокой конкурентности.
🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!
Подписаться