Уровни изоляции транзакций в базах данных: MVCC и 4 основных типа

Уровни изоляции определяют взаимодействие транзакций и степень их пересечения при параллельной работе. Разные уровни допускают или не допускают различные аномалии. Рассмотрим четыре основных уровня изоляции: Read Uncommitted, Read Committed, Repeatable Read и Serializable.

Read Uncommitted (Чтение незавершенных данных)

Это самый слабый уровень изоляции. Транзакция может видеть результаты других транзакций, даже незавершенных.

Пример:

  • Транзакция 1: SELECT баланс FROM аккаунт 1
  • Транзакция 2: Меняет баланс, но не совершает COMMIT.

Транзакция 1 увидит измененный баланс. Если Транзакция 2 откатится (ROLLBACK), повторный запрос Транзакции 1 вернет старый баланс. Это приводит к нескольким аномалиям:

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

Read Uncommitted редко используется, за исключением, возможно, аналитики больших данных, где точность данных менее критична.

Read Committed (Чтение завершенных данных)

Транзакция видит только данные, зафиксированные (COMMIT) другими транзакциями. Изменения, не зафиксированные COMMIT, не видны.

Этот уровень защищает от dirty read, но не от non-repeatable read и phantom read. Данные, прочитанные транзакцией, могут быть изменены другой транзакцией до завершения первой.

Этот уровень используется по умолчанию в PostgreSQL, MSSQL и Oracle.

Repeatable Read (Повторяемое чтение)

Пока транзакция не завершится, никто не может изменять или удалять строки, которые она уже прочитала. Это защищает от dirty read и non-repeatable read.

Пример:

Транзакция 2 не может изменить баланс, пока не завершится Транзакция 1.

Однако, Repeatable Read не защищает от phantom read. Другая транзакция может добавлять новые строки, удовлетворяющие условию запроса.

Этот уровень используется по умолчанию в MySQL (и в движке InnoDB).

Serializable (Сериализуемый)

Самый строгий уровень изоляции. Блокирует любые изменения, пока запущена транзакция. Транзакции выполняются последовательно, максимально изолируя друг от друга. Некоторые СУБД блокируют только задействованные строки, а не всю таблицу. Этот уровень исключает все аномалии. Однако, он наиболее ресурсоемкий и медленный.

Сравнение уровней изоляции

Уровень изоляции Dirty Read Non-repeatable Read Phantom Read
Read Uncommitted Да Да Да
Read Committed Нет Да Да
Repeatable Read Нет Нет Да
Serializable Нет Нет Нет

Выбор уровня изоляции

Выбор уровня изоляции зависит от баланса между целостностью данных и производительностью. В приложениях, где критична целостность, используется Serializable. В приложениях, где важна производительность, можно использовать более низкие уровни изоляции, смирившись с возможными аномалиями.

Другие аномалии

Помимо трех основных аномалий, на уровнях Read Uncommitted и Read Committed возможны:

  • Lost update (Потерянное обновление): Две транзакции одновременно изменяют одни и те же данные, и одно из изменений теряется.
  • Неупорядоченное выполнение: Может привести к неправильным результатам.

Специфические уровни изоляции и MVCC

Некоторые СУБД предлагают дополнительные уровни изоляции, такие как Read Stability (RS) и Cursor Stability (CS) (DB2), Snapshot Isolation (SQL Server) и Serializable Snapshot Isolation (SSI) (PostgreSQL). Эти уровни часто используют механизмы MVCC (Multi-Version Concurrency Control).

MVCC – метод управления конкурентным доступом, позволяющий нескольким транзакциям работать с данными одновременно без конфликтов. Он поддерживает высокую производительность и изоляцию, минимизируя блокировки и улучшая параллелизм. MVCC использует механизм многоверсионности: создаются новые версии данных; каждая транзакция видит данные в состоянии на момент ее начала; при записи создается новая версия строки; СУБД периодически очищает старые версии (сбор мусора). MVCC предотвращает dirty read, non-repeatable read и phantom read, сокращает блокировки для чтения, повышая производительность. Конфликты решаются при COMMIT. Реализация MVCC различается в разных СУБД.

Управление уровнями изоляции

Уровень изоляции устанавливается командой SET ISOLATION LEVEL. Команды различаются для разных СУБД. Примеры для MySQL:

  • SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; (для одной транзакции)
  • SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; (для всех транзакций в сессии)
  • SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; (для всех транзакций на сервере)

Взаимодействие транзакций с разными уровнями изоляции

Параллельная работа транзакций с разными уровнями изоляции может приводить к проблемам с видимостью данных и аномалиям. Транзакция с более высоким уровнем изоляции может блокировать ресурсы для транзакций с более низким уровнем. Транзакция с низким уровнем может видеть незавершенные изменения других транзакций.

Выбор уровня изоляции – важный аспект проектирования баз данных. Необходимо учитывать баланс между целостностью данных и производительностью, а также особенности используемой СУБД. MVCC играет ключевую роль в обеспечении параллелизма и изоляции транзакций.

Что будем искать? Например,программа