Открыть сервис

Аномалии транзакций

Аномалии транзакций — это ситуации, возникающие в системах управления базами данных (СУБД) и распределённых вычислительных системах при параллельном выполнении нескольких транзакций, которые приводят к нарушению согласованности данных, целостности или изоляции. Аномалии транзакций возникают, когда механизмы управления конкурентным доступом не обеспечивают должного уровня изоляции, что позволяет одной транзакции видеть промежуточные результаты другой или некорректно изменять данные. Они классифицируются по типам и тяжести последствий, а их предотвращение является одной из ключевых задач при проектировании транзакционных систем.

История

Концепция транзакций и связанных с ними аномалий возникла в 1970-х годах с развитием реляционных баз данных. В 1976 году Джим Грей в своей работе «Обоснование модели транзакций» впервые систематизировал проблемы параллельного доступа. В 1983 году Тео Хэрдер и Андреас Ройтер ввели аббревиатуру ACID (атомарность, согласованность, изоляция, долговечность), где изоляция напрямую связана с предотвращением аномалий. В 1992 году международный стандарт SQL-92 определил четыре уровня изоляции транзакций, каждый из которых допускает определённые типы аномалий. С развитием распределённых систем (NoSQL, блокчейн) в 2000-х годах были выявлены новые классы аномалий, такие как «фантомное чтение» и «потерянное обновление», которые не всегда покрываются классическими уровнями изоляции.

Классификация аномалий транзакций

Аномалии транзакций делятся на несколько основных типов в зависимости от того, какие операции (чтение, запись, удаление) выполняются параллельно и в каком порядке.

Грязное чтение (Dirty Read)

Грязное чтение — это аномалия, при которой одна транзакция читает данные, изменённые другой транзакцией, но ещё не зафиксированные (не завершённые командой COMMIT). Если вторая транзакция впоследствии откатывается (ROLLBACK), первая транзакция оказывается с некорректными данными, которые никогда не существовали в базе.

  • Пример: Транзакция A изменяет баланс счёта с 1000 на 500 рублей, но не завершает операцию. Транзакция B читает баланс (500 рублей) и на его основе выполняет расчёт. Затем транзакция A откатывается, и баланс возвращается к 1000 рублям. Транзакция B использовала несуществующие данные.
  • Условия возникновения: Допускается на уровне изоляции READ UNCOMMITTED (чтение незафиксированных данных).

Неповторяющееся чтение (Non-Repeatable Read)

Неповторяющееся чтение — это аномалия, при которой в рамках одной транзакции один и тот же запрос на чтение строки возвращает разные результаты в разные моменты времени. Это происходит, если другая транзакция изменяет (UPDATE) или удаляет (DELETE) эту строку и фиксирует изменения между двумя чтениями.

  • Пример: Транзакция A читает цену товара (100 рублей). Затем транзакция B изменяет цену на 150 рублей и фиксирует изменение. Транзакция A снова читает ту же строку и получает 150 рублей. Первое и второе чтения дали разные значения.
  • Условия возникновения: Допускается на уровнях изоляции READ UNCOMMITTED и READ COMMITTED (чтение зафиксированных данных).

Фантомное чтение (Phantom Read)

Фантомное чтение — это аномалия, при которой в рамках одной транзакции один и тот же запрос на чтение множества строк (например, SELECT с условием WHERE) возвращает разное количество строк в разные моменты времени. Это происходит, если другая транзакция вставляет (INSERT) новые строки, удовлетворяющие условию запроса, или удаляет существующие, и фиксирует изменения между двумя чтениями.

  • Пример: Транзакция A запрашивает список всех товаров с ценой выше 100 рублей (возвращает 10 строк). Затем транзакция B вставляет новый товар с ценой 200 рублей и фиксирует. Транзакция A повторяет запрос и получает 11 строк. «Фантом» — это строка, которая появилась «из ниоткуда».
  • Условия возникновения: Допускается на уровнях изоляции READ UNCOMMITTED, READ COMMITTED и REPEATABLE READ (повторяемое чтение).

Потерянное обновление (Lost Update)

Потерянное обновление — это аномалия, при которой две транзакции одновременно читают одно и то же значение, затем каждая изменяет его на основе прочитанного, и записывает результат. Изменение, сделанное первой транзакцией, перезаписывается второй, и данные первой транзакции теряются.

  • Пример: Транзакция A читает количество товара на складе (10 единиц). Транзакция B также читает 10 единиц. Транзакция A уменьшает количество на 2 (записывает 8). Транзакция B уменьшает количество на 3 (записывает 7, исходя из своего прочитанного значения 10). В результате реальное изменение должно было быть 10 - 2 - 3 = 5, но на складе стало 7. Изменение транзакции A потеряно.
  • Условия возникновения: Возникает на всех уровнях изоляции, если не используется блокировка строк или оптимистическая блокировка. Стандарт SQL-92 не относит потерянное обновление к аномалиям, но оно широко признаётся в литературе.

Аномалии сериализации (Serialization Anomalies)

В более высоких уровнях изоляции (например, SERIALIZABLE) могут возникать аномалии, связанные с нарушением сериализуемости — свойства, при котором результат параллельного выполнения транзакций эквивалентен результату их последовательного выполнения в некотором порядке.

  • Аномалия записи (Write Skew): Две транзакции читают перекрывающиеся наборы данных и затем записывают неперекрывающиеся данные, но на основе прочитанных значений. В результате возникает состояние, которое не могло бы возникнуть при последовательном выполнении. Пример: в системе бронирования два пользователя одновременно видят, что есть два свободных места в разных секциях, и каждый бронирует одно место. В итоге система может допустить, что оба места заняты, но при последовательном выполнении одно из мест могло быть заблокировано.
  • Аномалия чтения (Read Skew): Транзакция читает несогласованные данные из разных версий базы данных. Например, транзакция читает строку A из одной версии, а строку B — из другой, что приводит к нарушению ссылочной целостности.

Уровни изоляции транзакций

Для предотвращения аномалий в СУБД используются уровни изоляции, определённые стандартом SQL-92. Каждый уровень допускает определённые аномалии.

Уровень изоляцииГрязное чтениеНеповторяющееся чтениеФантомное чтение
READ UNCOMMITTEDДопускаетсяДопускаетсяДопускается
READ COMMITTEDПредотвращаетсяДопускаетсяДопускается
REPEATABLE READПредотвращаетсяПредотвращаетсяДопускается
SERIALIZABLEПредотвращаетсяПредотвращаетсяПредотвращается

Механизмы предотвращения

  • Блокировки (Locking): Пессимистический подход, при котором транзакция блокирует строки, таблицы или диапазоны данных для других транзакций. Используются разделяемые (S) и исключительные (X) блокировки.
  • Многоверсионность (MVCC): Оптимистический подход, при котором каждая транзакция работает со снимком данных на момент её начала. Изменения видны только после фиксации. MVCC предотвращает грязное чтение и неповторяющееся чтение, но не фантомное чтение без дополнительных механизмов.
  • Сериализация через графы (Serializable Snapshot Isolation): Расширение MVCC, которое отслеживает зависимости между транзакциями и откатывает те, которые могут привести к аномалиям сериализации.

Применение и значение

Понимание аномалий транзакций критически важно при проектировании систем, работающих с большими объёмами данных и высокими нагрузками (банковские системы, электронная коммерция, социальные сети, системы управления запасами). Выбор уровня изоляции влияет на производительность: более высокий уровень изоляции (SERIALIZABLE) гарантирует отсутствие аномалий, но снижает пропускную способность из-за блокировок и откатов. Более низкие уровни (READ COMMITTED) обеспечивают высокую производительность, но требуют от разработчиков учёта возможных аномалий в логике приложения.

В распределённых системах и блокчейн-платформах (например, Ethereum) аномалии транзакций могут проявляться в виде «двойных трат» (double-spending) — аналога потерянного обновления, когда одна и та же единица цифрового актива используется дважды. Для их предотвращения применяются консенсусные механизмы (Proof of Work, Proof of Stake) и протоколы атомарных свопов.

Критика и ограничения

Классическая модель аномалий, основанная на SQL-92, не охватывает все возможные сценарии в современных системах. Например, в распределённых базах данных (Cassandra, MongoDB) могут возникать аномалии, связанные с временными метками и частичной репликацией, которые не описываются стандартными уровнями изоляции. Кроме того, в системах с оптимистической блокировкой (MVCC) возможны аномалии сериализации, которые не были предусмотрены стандартом 1992 года. В 2008 году Майкл Стоунбрейкер и другие исследователи предложили расширенную классификацию, включающую «аномалии временных рядов» и «аномалии глобального порядка», что стимулировало развитие новых протоколов изоляции, таких как Serializable Snapshot Isolation.

Источники

  • Грей, Джим. «Обоснование модели транзакций». — 1976.
  • Хэрдер, Тео; Ройтер, Андреас. «Принципы транзакций в базах данных». — 1983.
  • Международный стандарт SQL-92 (ISO/IEC 9075:1992).
  • Стоунбрейкер, Майкл; и др. «Аномалии сериализации в современных СУБД». — 2008.
  • Учебник «Database Systems: The Complete Book» (Гарсия-Молина, Ульман, Уидом). — 2009.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →