Что гарантирует уровень изоляции транзакций SERIALIZABLE в SQL?

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

Ответ

Уровень изоляции SERIALIZABLE гарантирует полную изоляцию параллельных транзакций. Он создает иллюзию их последовательного выполнения, предотвращая все основные аномалии:

  • Грязное чтение (Dirty Read): Чтение незафиксированных данных другой транзакции.
  • Неповторяющееся чтение (Non-repeatable Read): Получение разных значений одной строки при повторном чтении в рамках одной транзакции.
  • Фантомное чтение (Phantom Read): Появление новых строк, удовлетворяющих условию запроса, при повторном чтении.

Как это работает: СУБД использует строгие блокировки (на уровне строк, диапазонов или таблиц) или механизмы управления параллелизмом на основе версий (MVCC) с проверкой сериализуемости, чтобы гарантировать такой результат.

Пример (PostgreSQL):

-- Сессия 1
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT SUM(balance) FROM accounts; -- Сканирование таблицы
-- В этот момент Сессия 2 не сможет вставить новую запись в `accounts`
-- или изменить существующие строки, попавшие в диапазон, до коммита Сессии 1.
-- ... некоторая обработка ...
COMMIT;

-- Сессия 2 (параллельно)
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
INSERT INTO accounts (user_id, balance) VALUES (123, 100); -- Будет заблокировано
-- Если бы уровень был READ COMMITTED, вставка прошла бы, создав "фантома" для Сессии 1.

Плюсы:

  • Максимальная целостность данных.
  • Предсказуемость результатов.

Минусы:

  • Низкая производительность и масштабируемость из-за интенсивных блокировок.
  • Высокий риск взаимоблокировок (deadlocks), которые СУБД вынуждена разрешать откатом одной из транзакций.

Применение: Используется для критически важных финансовых операций, где абсолютная корректность данных важнее скорости (например, двойная бухгалтерская запись). В большинстве приложений достаточно уровней READ COMMITTED или REPEATABLE READ.