← Назад ко всем вопросам

Как в PostgreSQL добиваются сериализуемости

1️⃣ Как кратко ответить

В PostgreSQL сериализуемость достигается с помощью механизма сериализуемой изоляции транзакций, который использует алгоритм Serializable Snapshot Isolation (SSI). Этот алгоритм позволяет транзакциям работать с моментальными снимками данных, предотвращая аномалии, такие как фантомные чтения, и обеспечивая поведение, эквивалентное последовательному выполнению транзакций.

2️⃣ Подробное объяснение темы

Сериализуемость — это самый строгий уровень изоляции транзакций в системах управления базами данных (СУБД). Он гарантирует, что результат выполнения параллельных транзакций будет таким же, как если бы эти транзакции выполнялись последовательно, одна за другой. В PostgreSQL сериализуемость достигается с помощью алгоритма Serializable Snapshot Isolation (SSI).

Зачем нужна сериализуемость?

Сериализуемость необходима для обеспечения целостности данных в условиях конкурентного доступа. Без нее параллельные транзакции могут привести к аномалиям, таким как:

  • Фантомные чтения: когда одна транзакция видит изменения, сделанные другой транзакцией, которые не должны быть видны.
  • Неповторяющиеся чтения: когда одна транзакция видит разные данные при повторном чтении в рамках одной транзакции.
  • Потерянные обновления: когда изменения, сделанные одной транзакцией, перезаписываются другой транзакцией.

Как работает Serializable Snapshot Isolation (SSI)?

SSI в PostgreSQL использует моментальные снимки данных для каждой транзакции. Это позволяет транзакциям работать с консистентным состоянием данных, существующим на момент их начала. Однако, в отличие от традиционного подхода блокировок, SSI отслеживает потенциальные конфликты между транзакциями и предотвращает их, если они могут привести к несериализуемым результатам.

Пример работы SSI

Рассмотрим две транзакции, которые выполняются параллельно:

  1. Транзакция A: Читает данные из таблицы и выполняет некоторые вычисления.
  2. Транзакция 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 мощным инструментом для работы с критически важными данными в условиях высокой конкурентности.

Тема: Базы данных и SQL
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки