Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як працює рівень Serializable у PostgreSQL і що таке помилка серіалізації?

Serializable гарантує, що результат паралельних транзакцій буде таким, ніби вони виконувалися по черзі в якомусь порядку. Жодних аномалій паралельності - навіть тих, від яких не рятує Repeatable Read.

Класична аномалія, яку ловить лише Serializable - write skew:

-- У лікарні має чергувати хоча б один лікар. Чергують двоє.
-- Транзакція A:                          -- Транзакція B:
SELECT count(*) FROM doctors              SELECT count(*) FROM doctors
WHERE on_call;          -- 2              WHERE on_call;          -- 2
UPDATE doctors SET on_call = false        UPDATE doctors SET on_call = false
WHERE id = 1;                             WHERE id = 2;
COMMIT;                                   COMMIT;
-- Результат: не чергує ніхто

Кожна транзакція окремо коректна, а разом вони порушили правило. На Repeatable Read обидві закомітяться.

Як PostgreSQL це реалізує - SSI (Serializable Snapshot Isolation): транзакції не блокують одна одну, а база відстежує залежності між тим, що кожна прочитала й записала. Якщо виявлено небезпечний цикл залежностей, одна з транзакцій отримує помилку:

ERROR: could not serialize access due to read/write dependencies among transactions
SQLSTATE 40001

Помилка серіалізації - не збій, а частина контракту. Застосунок мусить повторити всю транзакцію з початку:

DB::transaction(function () {
    // ...
}, attempts: 3);   // Laravel повторить при deadlock чи serialization failure

Ціна Serializable:

  • Повтори транзакцій - логіка має бути ідемпотентною до коміту (без листів і HTTP-запитів усередині).
  • Додаткові накладні витрати на відстеження залежностей.
  • Більше відкатів під високою конкуренцією.

Коли обирати: складні бізнес-правила, що залежать від кількох рядків (бронювання, ліміти, інваріанти «хоча б один / не більше N»), і коли розставляти блокування вручну складно. Для простих випадків часто достатньо атомарного UPDATE чи SELECT ... FOR UPDATE.

Докладніше в документації: Рівень ізоляції Serializable

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання