Транзакция ACID
Транзакция ACID — это последовательность операций с данными в системе управления базами данных (СУБД), которая гарантированно выполняется как единое целое, сохраняя четыре фундаментальных свойства: атомарность (Atomicity), согласованность (Consistency), изолированность (Isolation) и долговечность (Durability). Аббревиатура ACID была введена в начале 1980-х годов Тео Хардером и Андреасом Ройтером для формализации требований к надёжности транзакций в распределённых информационных системах. Транзакции ACID являются основой работы большинства реляционных СУБД (например, PostgreSQL, Oracle Database, Microsoft SQL Server) и обеспечивают целостность данных даже при сбоях оборудования, ошибках программного обеспечения или параллельном доступе множества пользователей.
История и происхождение
Понятие транзакции как единицы работы с данными возникло в 1960-х годах в связи с развитием мейнфреймов и первых банковских систем. В 1970-х годах, с появлением реляционной модели данных, предложенной Эдгаром Коддом, потребовались формальные гарантии целостности при одновременном выполнении запросов. В 1983 году в статье «Principles of Transaction-Oriented Database Recovery» Тео Хардер и Андреас Ройтер впервые сформулировали требования к транзакциям, которые позже получили название ACID. Эта работа легла в основу стандартов обработки транзакций ISO/IEC 10026 (1992) и последующих спецификаций.
В 1990-х годах, с распространением интернета и электронной коммерции, транзакции ACID стали критически важны для систем бронирования, финансовых операций и управления запасами. В 2000-х годах, с появлением NoSQL-баз данных (например, MongoDB, Cassandra), некоторые из них отказались от полной поддержки ACID в пользу масштабируемости и производительности, что привело к появлению концепции BASE (Basically Available, Soft state, Eventually consistent). Однако к 2020-м годам многие NoSQL-системы начали добавлять частичную поддержку ACID-транзакций (например, MongoDB с версии 4.0, Apache Cassandra с версии 4.0).
Свойства ACID
Атомарность (Atomicity)
Атомарность означает, что транзакция выполняется как неделимая единица: либо все её операции успешно завершаются, либо ни одна из них не применяется к базе данных. Если в процессе выполнения транзакции происходит сбой (например, отключение питания или ошибка в операции), система откатывает все изменения, возвращая базу данных в состояние, предшествовавшее началу транзакции. Этот механизм реализуется через журнал транзакций (журнал упреждающей записи — Write-Ahead Log, WAL). Пример: при переводе денег между счетами атомарность гарантирует, что списание с одного счёта и зачисление на другой произойдут одновременно или не произойдут вовсе, исключая ситуацию, когда деньги списаны, но не зачислены.
Согласованность (Consistency)
Согласованность гарантирует, что после завершения транзакции база данных переходит из одного корректного состояния в другое, соблюдая все заданные ограничения целостности: первичные и внешние ключи, уникальные индексы, проверочные условия (CHECK), триггеры и бизнес-правила. Транзакция не может нарушить инварианты базы данных. Например, если в таблице «Студенты» задано ограничение, что возраст должен быть не менее 16 лет, то транзакция, пытающаяся вставить запись с возрастом 15, будет отклонена. Согласованность обеспечивается не только СУБД, но и корректным кодом приложения, которое инициирует транзакцию.
Изолированность (Isolation)
Изолированность определяет, насколько результаты одной транзакции видны другим параллельно выполняющимся транзакциям. Стандарт SQL-92 определяет четыре уровня изолированности, каждый из которых решает определённые проблемы параллельного доступа:
- Read Uncommitted (чтение незафиксированных данных): транзакция может читать данные, изменённые, но ещё не зафиксированные другой транзакцией. Это самый низкий уровень, допускающий «грязное чтение» (dirty read). Используется редко.
- Read Committed (чтение зафиксированных данных): транзакция видит только те изменения, которые уже зафиксированы другими транзакциями. Это уровень по умолчанию в PostgreSQL, Oracle, SQL Server. Предотвращает грязное чтение, но допускает неповторяющееся чтение (non-repeatable read) — когда повторное чтение той же строки в рамках одной транзакции даёт разные результаты.
- Repeatable Read (повторяемое чтение): гарантирует, что если транзакция один раз прочитала строку, то при повторном чтении в рамках той же транзакции она увидит те же данные, даже если другая транзакция их изменила и зафиксировала. Предотвращает неповторяющееся чтение, но допускает фантомное чтение (phantom read) — появление новых строк, соответствующих условию запроса. Уровень по умолчанию в MySQL (InnoDB).
- Serializable (сериализуемый): самый строгий уровень, при котором транзакции выполняются так, как если бы они были запущены последовательно, одна за другой. Полностью исключает грязное, неповторяющееся и фантомное чтение. Реализуется через блокировки или механизм многоверсионного управления параллелизмом (MVCC) с проверкой конфликтов.
СУБД реализуют изолированность с помощью блокировок (блокировки строк, страниц, таблиц) или многоверсионности (MVCC), когда каждая транзакция видит снимок данных на момент своего начала.
Долговечность (Durability)
Долговечность гарантирует, что после успешного завершения транзакции (фиксации, COMMIT) все её изменения сохраняются в базе данных даже при немедленном сбое системы (например, отключении питания). Реализуется через запись изменений в энергонезависимую память (жёсткий диск, SSD) с использованием журнала транзакций (WAL) и контрольных точек (checkpoints). В современных СУБД долговечность может быть смягчена для повышения производительности (например, опция synchronous_commit = off в PostgreSQL), но по умолчанию она является обязательным свойством.
Реализация в СУБД
Реляционные СУБД
Большинство реляционных СУБД (PostgreSQL, MySQL с движком InnoDB, Oracle Database, Microsoft SQL Server, SQLite) полностью поддерживают ACID-транзакции. Реализация включает:
- Журнал упреждающей записи (WAL): все изменения сначала записываются в журнал, а затем применяются к основным файлам данных. При сбое система восстанавливает состояние по журналу.
- Многоверсионное управление параллелизмом (MVCC): позволяет читателям не блокировать писателей и наоборот, создавая для каждой транзакции снимок данных.
- Блокировки: блокировки строк, таблиц или предикатов для обеспечения изолированности на уровне Serializable.
- Точки сохранения (savepoints): позволяют откатить часть транзакции без полного отката.
NoSQL-системы
Некоторые NoSQL-базы данных (например, MongoDB, Apache Cassandra, Redis) изначально не поддерживали ACID-транзакции, но с 2010-х годов начали добавлять частичную поддержку. Например:
- MongoDB (с версии 4.0) поддерживает многодокументные ACID-транзакции, но с ограничениями по производительности и не на всех конфигурациях.
- Apache Cassandra (с версии 4.0) ввела поддержку лёгких транзакций (LWT) с изолированностью Serializable для отдельных операций.
- Redis поддерживает атомарные операции и транзакции с помощью команд MULTI/EXEC, но не гарантирует изолированность в полном объёме.
Распределённые системы
В распределённых базах данных (например, Google Spanner, CockroachDB, Yandex ClickHouse) реализация ACID усложняется из-за необходимости синхронизации между узлами. Такие системы используют протоколы распределённой фиксации (например, двухфазная фиксация — 2PC, трёхфазная фиксация — 3PC) или алгоритмы консенсуса (Raft, Paxos) для обеспечения атомарности и долговечности.
Применение
Транзакции ACID критически важны в следующих областях:
- Финансовые системы: банковские переводы, обработка платежей, бухгалтерский учёт. Гарантируют, что деньги не пропадут и не задвоятся.
- Электронная коммерция: оформление заказов, управление запасами. Транзакция гарантирует, что товар не будет продан дважды и что заказ будет создан полностью.
- Бронирование: авиабилеты, гостиницы, билеты на мероприятия. Исключают двойное бронирование одного места.
- Медицинские информационные системы: запись пациентов, назначение лекарств, результаты анализов. Обеспечивают целостность и согласованность данных.
- Телекоммуникации: биллинг, управление абонентами, тарификация звонков.
Критика и альтернативы
ACID-транзакции обеспечивают высокую надёжность, но имеют недостатки:
- Производительность: блокировки и журналирование снижают скорость выполнения, особенно при высокой конкурентности.
- Масштабируемость: в распределённых системах поддержка ACID требует сложных протоколов (2PC, Paxos), что увеличивает задержки и снижает доступность.
- Жёсткость: требования согласованности могут быть избыточны для систем, где допустима временная несогласованность (например, социальные сети, аналитика).
В ответ на эти ограничения была предложена модель BASE (Basically Available, Soft state, Eventually consistent), которая используется в некоторых NoSQL-системах (Cassandra, DynamoDB). В модели BASE допускается временное нарушение согласованности, которая восстанавливается со временем. Однако для критически важных приложений (финансы, медицина) ACID остаётся стандартом.
Интересные факты
- Термин ACID был придуман как игра слов с аббревиатурой BASE (основание), чтобы подчеркнуть противопоставление моделей.
- В 2012 году компания Google представила систему Spanner, которая поддерживает ACID-транзакции в глобальном масштабе с использованием атомных часов и GPS для синхронизации времени.
- В 2020 году в PostgreSQL 13 была добавлена поддержка параллельной фиксации транзакций, что ускорило выполнение массовых операций.
Источники
- Хардер Т., Ройтер А. «Principles of Transaction-Oriented Database Recovery» (1983).
- ISO/IEC 10026-1:1992 «Information technology — Open Systems Interconnection — Distributed Transaction Processing».
- Грей Д., Ройтер А. «Transaction Processing: Concepts and Techniques» (1993).
- Документация PostgreSQL: «Transaction Isolation Levels» (2024).
- Документация MongoDB: «Transactions» (2024).
- Документация Apache Cassandra: «Lightweight Transactions» (2024).
- Статья «ACID vs. BASE: The Shifting pH of Database Transaction Processing» (2008).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →