Как уровень изоляции транзакций Serializable определяет, какая транзакция будет зафиксирована?

«Как уровень изоляции транзакций Serializable определяет, какая транзакция будет зафиксирована?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Serializable — это самый строгий уровень изоляции транзакций в SQL. Он не "выбирает" транзакцию для фиксации, а гарантирует их полную сериализуемость: результат параллельного выполнения транзакций должен быть идентичен результату их последовательного выполнения.

Как это работает: СУБД (как PostgreSQL или Oracle) использует механизмы (блокировки или MVCC — Multi-Version Concurrency Control) для предотвращения всех аномалий:

  • Грязное чтение (Dirty Read)
  • Неповторяемоеся чтение (Non-repeatable Read)
  • Фантомное чтение (Phantom Read)

Процесс при конфликте:

  1. Две транзакции, работающие на уровне SERIALIZABLE, выполняются параллельно.
  2. Если их совместное выполнение может привести к результату, отличному от последовательного, СУБД обнаруживает конфликт сериализации.
  3. Одна из транзакций аварийно завершается с ошибкой (например, SQLSTATE 40001 или "Serialization Failure").
  4. Приложение должно перезапустить эту откатившуюся транзакцию.

Пример:

-- Транзакция 1
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT SUM(balance) FROM accounts; -- Допустим, сумма = 1000

-- Транзакция 2 (выполняется параллельно)
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE accounts SET balance = balance + 100 WHERE id = 1;
COMMIT; -- Успешно фиксируется

-- Теперь Транзакция 1 пытается выполнить операцию, зависящую от первоначального состояния
UPDATE accounts SET balance = balance * 1.1;
COMMIT; -- СУБД откатит эту транзакцию с ошибкой сериализации.

Итог: Уровень SERIALIZABLE обеспечивает максимальную целостность, но требует обработки ошибок повтора и может снижать пропускную способность.