Требования ACID. BASE модель. CAP теорема

Table of Contents

Что такое ACID?

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

Клиент размещает заказ, и ваша система должна вычесть товар из запасов, списать средства с кредитной карты клиента и зарегистрировать продажу в вашей системе учета — и все это одновременно.

Что произойдет, если платеж не пройдет, но ваш счет в инвентаре уже будет уменьшен? Или если ваше приложение зависнет на полпути процесса?

Вот тут-то и вступают в игру транзакции ACID. Они гарантируют, что все шаги в таких критических операциях происходят надежно и последовательно.

ACID (atomicity, consistency, isolation, durability) — набор требований к транзакционной системе, обеспечивающий наиболее надёжную и предсказуемую её работу — атомарность, согласованность, изоляцию, устойчивость. Сформулированы в конце 1970-х годов Джимом Греем.

В этой статье мы подробно рассмотрим значение каждого свойства ACID, почему они важны и как они реализованы в базах данных.

Что такое транзакция базы данных?

Транзакция в контексте баз данных — это последовательность из одной или нескольких операций (например, вставка, обновление или удаление записей), которые база данных рассматривает как одно действие. Она либо полностью завершается успешно, либо полностью терпит неудачу, без промежуточных состояний.

Пример: Банковский перевод

Когда вы отправляете деньги другу, происходят две вещи:

  • Деньги списываются с вашего счета.
  • Деньги зачисляются на их счет.

Эти два шага образуют одну транзакцию. Если один из шагов не выполнен, оба отменяются.

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

Например:

  • Частичные обновления: Ваши деньги списываются, но Ваш друг их не получает.
  • Конфликты: два человека бронируют последний билет в кино одновременно.

Транзакции решают эти проблемы, применяя такие правила, как свойства ACID (атомарность, согласованность, изолированность, долговечность).

Теперь давайте рассмотрим каждое из свойств ACID.

Atomicity (Атомарность)

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

Если какая-либо часть транзакции завершается неудачей, вся транзакция откатывается, а база данных восстанавливается до состояния, в котором она была до начала транзакции.

Пример: В транзакции денежного перевода, если кредитный шаг не удается, дебетовый шаг не может быть оставлен сам по себе. Это предотвращает несоответствующие состояния, такие как «деньги исчезают» с одного счета, не появляясь на другом.

Атомарность устраняет сложность ручной отмены изменений, если что-то пойдет не так.

Как базы данных реализуют атомарность

Базы данных используют два ключевых механизма для обеспечения атомарности.

1. Журналы транзакций (журналы упреждающей записи — Write-Ahead Log, WAL)


У WAL есть несколько используемых переводов:

  • Журнал предзаписи
  • Журнал упреждающей записи
  • Транзакционный журнал
  • Упреждающее журналирование

Реализация:

  • Каждая операция записывается в журнал (WAL), прежде чем она будет применена к фактической таблице базы данных.
  • В случае сбоя база данных использует этот журнал для отмены незавершенных изменений.

Пример:

После того, как запись WAL безопасно помещена на диск, база данных приступает к изменению страниц в памяти, содержащих строки для учетной записи A и учетной записи B.

В случае успеха операций:

  • База данных отмечает идентификатор транзакции 12345 как зафиксированный в журнале транзакций.
  • Недавно обновленные балансы для A и B в конечном итоге будут сброшены из памяти в соответствующие файлы данных на диске.

Если база данных выходит из строя после записи в журнал, но до полного обновления файлов данных, WAL предоставляет способ восстановления:

  • При перезапуске база данных проверяет WAL.
  • Видно, что транзакция 12345 была зафиксирована.
  • Он повторно применяет операции UPDATE, чтобы гарантировать правильность окончательных балансов в файлах данных.
  • Если транзакция не была зафиксирована (или была помечена как «in progress») на момент сбоя, база данных откатит эти изменения, используя информацию в журнале, оставив таблицу такой, как будто транзакция никогда не происходила.

2. Протоколы фиксации и отката (Commit/Rollback Protocols)

Базы данных предоставляют такие команды BEGIN TRANSACTION, как COMMIT, и ROLLBACK.

  • BEGIN TRANSACTION — начало транзакции.
  • COMMIT — фиксация изменений.
  • ROLLBACK — откат изменений.

Любые изменения, внесенные между BEGIN TRANSACTION и COMMIT считаются «выполняемыми» и не будут применены навсегда, если транзакция не будет успешно зафиксирована.

Если какой-либо шаг не выполнен или вы явно указали ROLLBACK, все изменения, внесенные с момента начала транзакции, будут отменены.

Пример:

Consistency (Согласованность)

Согласованность в контексте ACID-транзакций гарантирует, что любая транзакция переводит базу данных из одного допустимого состояния в другое допустимое состояние — никогда не оставляя её в некорректном или «невалидном» состоянии.

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

Если транзакция пытается нарушить эти правила, она не будет зафиксирована, и база данных вернётся в предыдущее состояние.

Пример:

В базе данных электронной коммерции есть две таблицы:

  • products (со столбцами: product_id, stock_quantity, и т.д.)
  • orders (со столбцами: order_id, product_id, quantity, и т.д.)
  • Ограничение: Нельзя разместить заказ на товар, если запрашиваемое количество (quantity) превышает stock_quantity в таблице products.

Transaction Flow (Последовательность транзакции):

Если stock_quantity товара было 8 (меньше, чем количество, которое мы пытаемся заказать), база данных обнаружит, что новое значение будет -2, что нарушает правило согласованности (значение не должно становиться отрицательным).

Транзакция завершится с ошибкой или вызовет откат (rollback), предотвращая попадание базы данных в некорректное состояние.

Как реализовать согласованность?

Ограничения схемы базы данных

  • Ограничения NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK и другие определения схемы предотвращают ввод недопустимых данных.

Триггеры и хранимые процедуры

  • Триггеры могут автоматически проверять дополнительные правила при вставке, обновлении или удалении строк.
  • Хранимые процедуры могут содержать логику для проверки данных перед фиксацией изменений.

Защита на уровне приложения

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

Isolation (Изоляция)

Изоляция гарантирует, что одновременно выполняющиеся транзакции не вмешиваются в промежуточные состояния друг друга.

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

Без изоляции две или более транзакции могли бы читать и записывать частичные или незавершённые данные друг от друга, что привело бы к некорректным или несогласованным результатам.

Благодаря изоляции разработчики могут более надёжно прогнозировать, как изменения данных будут видны другим транзакциям.

Аномалии конкурентного доступа / Аномалии параллелизма

Чтобы понять, как работает изоляция, полезно рассмотреть, какие проблемы могут возникнуть при её отсутствии. Основные аномалии конкурентного доступа включают:

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

  • Транзакция A читает данные, которые были изменены, но ещё не зафиксированы транзакцией B.
  • Если затем транзакция B выполняет откат (ROLLBACK), транзакция A окажется с недействительным или «грязным» значением, которое фактически никогда не существовало в зафиксированном состоянии.

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

  • Транзакция A считывает одни и те же строки несколько раз во время своего выполнения, но видит разные данные, поскольку другая транзакция обновила или удалила эти строки между чтениями A.

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

  • Транзакция A несколько раз читает одну и ту же строку (или строки) во время выполнения.
  • Между этими чтениями другая транзакция изменяет или удаляет соответствующие строки.
  • В результате транзакция A видит разные значения при повторных чтениях одной и той же строки.

Уровни изоляции

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

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

Давайте рассмотрим четыре распространенных уровня изоляции.

Read Uncommitted (Чтение неподтверждённых данных)

Разрешает грязное чтение; транзакции могут видеть незафиксированные изменения.

Используется редко, так как может привести к серьезным аномалиям.

Read Committed (Чтение подтверждённых данных)

Транзакция видит только те данные, которые были зафиксированы на момент чтения.

Предотвращает «грязное» чтение, однако неповторяющиеся чтения и фантомные чтения все еще могут иметь место.

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

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

Предотвращает грязное чтение и неповторяющееся чтение, но фантомное чтение все равно может произойти (в зависимости от ядра базы данных).

Serializable (Сериализуемость)

Самый высокий уровень изоляции, при котором все транзакции происходят последовательно, по одной за раз.

Предотвращает грязное чтение, неповторяющееся чтение и фантомное чтение.

Самый затратный с точки зрения производительности и параллелизма, поскольку может потребоваться больше блокировок или больше проверок конфликтов.

Как базы данных обеспечивают изоляцию

Блокировки (Locking)

  • Пессимистичный контроль конкурентности (Pessimistic Concurrency Control)
  • Строки или таблицы блокируются, чтобы никакая другая транзакция не могла их читать или изменять, пока блокировка не будет снята.
  • Может привести к блокировке (blocking) или взаимоблокировке (deadlock), если несколько транзакций конкурируют за одни и те же блокировки.

MVCC (Многоверсионное управление конкурентным доступом — Multi-Version Concurrency Control)

  • Оптимистичный контроль конкурентности (Optimistic Concurrency Control)
  • Вместо блокировки чтения база данных хранит несколько версий одной и той же строки.
  • Читающие транзакции видят согласованный снимок данных (как если бы они смотрели на состояние в определённый момент времени), а записывающие транзакции создают новую версию строки при обновлении.
  • Этот подход уменьшает конфликты блокировок, но требует тщательного управления версиями строк и их очистки (например, механизма vacuum в PostgreSQL).

Изоляция снапшотов (Snapshot Isolation)

  • Вариант MVCC, при котором каждая транзакция видит данные в том виде, в каком они были в начале её выполнения (или на согласованной точке во времени).
  • Предотвращает грязные чтения (Dirty Reads) и неповторяемые чтения (Non-Repeatable Reads).
  • Фантомные чтения (Phantom Reads) всё ещё возможны, если уровень изоляции не установлен в Serializable.

Durability (Устойчивость/Надежность/Долговечность)

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

Другими словами, как только транзакция завершается, данные фиксируются навсегда и не могут просто исчезнуть.

Как базы данных обеспечивают долговечность

Журнал транзакций (Write-Ahead Logging, WAL)

Большинство реляционных баз данных используют журнал упреждающей записи (WAL) для сохранения изменений до их записи в основные файлы данных:

  • Write Changes to WAL (Запись изменений в WAL): предполагаемые операции (обновления, вставки, удаления) записываются в WAL на долговременном носителе (диске).
  • Commit the Transaction (Зафиксировать транзакцию): как только запись WAL будет безопасно сохранена, база данных может пометить транзакцию как зафиксированную.
  • Apply Changes to Main Data Files (Применить изменения к основным файлам данных): обновленные данные в конечном итоге записываются в основные файлы — возможно, сначала в память, а затем сбрасываются на диск.

В случае сбоя базы данных во время восстановления она использует WAL :

  • Redo (Повторить): любые зафиксированные транзакции, еще не отраженные в основных файлах, применяются повторно.
  • Undo (Отменить): все незавершенные (незафиксированные) транзакции откатываются для сохранения согласованности базы данных.

Репликация / Избыточность (Replication / Redundancy)

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

  • Синхронная репликация: записи немедленно копируются на несколько узлов или центров обработки данных. Транзакция помечается как зафиксированная, только если первичный узел и по крайней мере одна реплика подтверждают, что она безопасно сохранена.
  • Асинхронная репликация: изменения в конечном итоге синхронизируются с другими узлами, но существует (небольшое) окно, в котором может произойти потеря данных, если основной узел выйдет из строя до обновления реплики.

Backups (Резервные копии)

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

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

Сравнительная таблица требований ACID в различных транзакционных СУБД

База данныхAtomicity (Атомарность)Consistency (Согласованность)Isolation (Изоляция)Durability (Надёжность)
MSSQLИспользует журналы транзакций (Write-Ahead Logging, WAL), транзакции полностью атомарныГарантирует согласованность через строгие ограничения и триггерыПоддерживает уровни изоляции: Read Uncommitted, Read Committed, Repeatable Read, Serializable, SnapshotЖурнал транзакций обеспечивает сохранность данных даже при сбоях
PostgreSQLИспользует WAL для атомарности транзакцийПоддерживает строгие ограничения целостностиMVCC (многоверсионность), уровни изоляции: Read Committed, Repeatable Read, SerializableWAL обеспечивает надежность, данные сохраняются даже при сбое
MySQL (InnoDB)InnoDB использует двухфазную фиксацию (2PC) и WALОграничения целостности и внешние ключи поддерживаютсяПоддержка уровней изоляции: Read Uncommitted, Read Committed, Repeatable Read, SerializableИспользует WAL, поддерживает автоматическое восстановление
OracleИспользует механизмы undo/redo для атомарностиСтрогая согласованность через ограничения и триггерыИспользует MVCC, уровни изоляции: Read Committed, SerializableНадежное восстановление через redo-логи
IBM Db2Использует WAL, гарантирует атомарностьОграничения целостности, поддержка ACID-совместимых операцийПоддерживает уровни изоляции: Cursor Stability (CS), Repeatable Read (RR), SerializableНадежность обеспечивается за счет WAL и резервного копирования
MariaDB (InnoDB, Aria)InnoDB аналогичен MySQL, Aria поддерживает транзакции с журналированиемПоддержка ограничений целостностиMVCC (InnoDB), разные уровни изоляцииЖурнал транзакций и восстановление
FirebirdИспользует журнал изменений и механизм UndoСтрогая целостность данныхПоддерживает Snapshot Isolation, Read Committed, SerializableЖурнал транзакций защищает данные
SQLiteИспользует механизм журнала транзакций (WAL)Ограниченная поддержка ограничений целостностиПоддерживает уровни: Read Uncommitted, SerializableДанные сохраняются в файле базы данных, но надежность зависит от настроек

Пояснение по некоторой терминологии СУБД

Write-Ahead Logging (WAL) — Журнал опережающей записи – это метод, при котором изменения записываются сначала в журнал (лог), а затем применяются к основной базе данных. Это обеспечивает надежность транзакций, так как в случае сбоя можно восстановить данные из журнала.

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

Чем выше уровень, тем меньше конкуренция, но выше задержки и блокировки

  • Cursor Stability (CS) – промежуточный уровень изоляции в IBM Db2, удерживает блокировку только на текущей строке, а не на всей транзакции.
  • Read Uncommitted – самый низкий уровень, позволяет читать «грязные» (незафиксированные) данные других транзакций.
  • Read Committed – транзакция видит только зафиксированные данные, но могут появляться «фантомные» чтения (изменения других транзакций).
  • Repeatable Read – предотвращает «фантомные» чтения, но другие транзакции могут добавлять новые строки.
  • Serializable – самый строгий уровень, транзакции выполняются последовательно, исключая все виды аномалий.
  • Snapshot – транзакция видит данные в момент начала работы (используется в MVCC), обеспечивая изоляцию без блокировок.

MVCC (Multi-Version Concurrency Control)

Многоверсионное управление конкурентным доступом – механизм, позволяющий транзакциям работать с разными версиями данных без блокировок. Это улучшает производительность и снижает конфликты.

Двухфазная фиксация (2PC — Two-Phase Commit)

Протокол, используемый при распределённых транзакциях. Он работает в два шага:

  • Подготовка – все узлы подтверждают готовность зафиксировать транзакцию.
  • Фиксация – если все согласны, транзакция фиксируется. Если хоть один отказывает, транзакция откатывается.

Механизмы undo/redo для атомарности

  • Undo (отмена) – используется для отката изменений, если транзакция прервана.
  • Redo (повторное выполнение) – применяется для восстановления завершённых транзакций после сбоя.

Redo-логи

Логи, содержащие информацию о зафиксированных транзакциях, чтобы можно было повторить изменения после сбоя системы.

Журнал транзакций и восстановление

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

BASE-модель для NoSQL баз данных

В отличие от ACID-модели, которая ориентирована на строгую согласованность, BASE (Basically Available, Soft state, Eventually consistent) подходит для распределённых NoSQL баз данных, где важнее доступность и масштабируемость.

Во второй половине 2000-х годов сформулирован подход к построению распределённых систем, в которых требования целостности и доступности выполнены не в полной мере, названый акронимом BASE (Basically Available, Soft-state, Eventually consistent — базовая доступность, неустойчивое состояние, согласованность в конечном счёте), при этом такой подход напрямую противопоставляется ACID.

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

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

Согласованности в конечном счёте, трактующейся как возможность противоречивости данных в некоторых случаях, но при обеспечении согласования в практически обозримое время, посвящено значительное количество самостоятельных исследований.

BASE: Basically Available / Soft state / Eventually consistent

Basically Available (Базовая доступность)

  • Система гарантирует доступность данных даже в случае частичных отказов.
  • Данные могут быть не полностью согласованными, но запросы не блокируются.
  • Например, если один сервер недоступен, другой всё равно может выдать старую версию данных.

Soft state (Гибкое состояние)

  • Состояние системы может изменяться со временем даже без новых запросов.
  • Это значит, что данные в разных узлах могут временно отличаться из-за асинхронной репликации.
  • Например, если запись обновилась на одном сервере, изменения могут дойти до других с задержкой.

Eventually consistent (Окончательная согласованность)

  • Система со временем достигает согласованности, но не сразу.
  • Это позволяет масштабировать базы данных и повышать отказоустойчивость.
  • Например, в DynamoDB или Cassandra данные могут быть сначала разными на разных узлах, но через некоторое время синхронизируются.

Когда выбирают BASE вместо ACID?

BASE подходит, когда:

  • Важнее скорость и отказоустойчивость, чем мгновенная согласованность.
  • Данные могут быть временно несогласованными, но постепенно синхронизируются.
  • Используются распределённые NoSQL базы (Cassandra, DynamoDB, Riak, CouchDB).

В отличие от ACID, BASE жертвует строгой целостностью ради масштабируемости и высокой доступности.

Примеры популярных NoSQL баз данных

Документные базы данных (хранят данные в виде JSON, BSON, XML)

  • MongoDB – самая популярная документная NoSQL БД, поддерживает гибкие схемы данных.
  • CouchDB – использует JSON-документы и репликацию, оптимизирована для распределённых систем.
  • Firebase Firestore – облачная NoSQL база от Google, активно используется в мобильных и веб-приложениях.

Ключ-значение (Key-Value) базы данных (быстрый доступ по ключу)

  • Redis – сверхбыстрая in-memory NoSQL база, часто используется для кеширования.
  • Amazon DynamoDB – облачная NoSQL база от AWS, хорошо масштабируется.
  • Riak KV – распределённая база данных с высокой отказоустойчивостью.

Графовые базы данных (оптимизированы для работы с графами и связями)

  • Neo4j – самая популярная графовая база, используется в социальных сетях, рекомендательных системах.
  • ArangoDB – мультипарадигменная база (графы + документы + ключ-значение).
    Amazon Neptune – облачная графовая БД от AWS, поддерживает Gremlin и SPARQL.

Колонночные базы данных (работают с огромными объёмами данных, оптимизированы для аналитики)

  • Apache Cassandra – масштабируемая распределённая NoSQL БД от Facebook.
  • HBase – построена на Hadoop, подходит для Big Data.
  • Google Bigtable – облачная колонночная база от Google.

Time-Series базы данных (оптимизированы для работы с временными рядами)

  • InfluxDB – популярная база для сбора и анализа данных о временных рядах (например, IoT-устройства, логи).
  • TimescaleDB – расширение PostgreSQL для работы с временными рядами.
  • OpenTSDB – работает поверх HBase, предназначена для хранения больших объёмов временных данных.

Как принцип BASE обеспечивается в СУБД?

Вместо строгой ACID-согласованности базы BASE обеспечивают «размытую» согласованность, используя асинхронную репликацию, механизмы конфликтного разрешения и компромиссные модели консистентности.

Ниже будут рассмотрены некоторые из приемов, которые обеспечивают тот или иной пункт модели BASE.

Basically Available (Базовая доступность)

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


Даже если часть системы выходит из строя, база продолжает работать.

  • Репликация данных – копии хранятся на нескольких узлах.
  • Eventual Consistency – данные синхронизируются позже, но система не блокируется.
  • Шардирование (разделение данных) – нагрузка делится на множество узлов.

Пример:

  • Cassandra или DynamoDB используют quorum-репликацию, где большинство узлов должны подтвердить запись.
  • Redis Cluster распределяет данные по узлам, гарантируя высокую доступность.

Soft State (Гибкое состояние)

Гибкое/Мягкое состояние здесь означает, что любые данные могут находиться в промежуточных или временных состояниях и в некоторый момент изменяться «сами по себе», без внешних событий или поступления новых данных. Эта концепция отражает неопределенное состояние записи, которую обновляют несколько приложений одновременно. Значение такой записи будет окончательно определено только после завершения всех транзакций. Например, если пользователи редактируют сообщение в социальной сети, внесенные ими изменения могут быть не сразу видны другим пользователям. Через некоторое время система учтет все внесенные изменения, и произойдет обновление сообщения, хотя ни один пользователь его не инициировал.


Система может изменяться даже без новых транзакций.

  • Асинхронная репликация – данные распространяются между узлами не сразу, а с задержкой.
  • Кэширование – данные могут храниться в распределённых узлах и устаревать.
  • Механизмы разруливания конфликтов – например, last-write-wins (LWW), CRDT (Conflict-Free Replicated Data Types).

Пример:

  • В Riak можно настроить стратегию разрешения конфликтов – брать последнее изменение или объединять данные.
  • В MongoDB при репликации вторичные узлы могут временно содержать устаревшие данные.

Eventually Consistent (Окончательная согласованность)

Окончательная согласованность означает, что запись достигнет согласованности не сразу, а после завершения всех одновременных обновлений. После этого все приложения, запрашивающие эту запись, увидят одно и то же значение. Давайте рассмотрим в качестве примера распределенную систему редактирования документов, в которой несколько пользователей могут одновременно редактировать документ. Если пользователь A и пользователь B одновременно редактируют один и тот же раздел документа, их локальные копии могут временно различаться, пока не завершатся процессы распространения и синхронизации. Однако со временем, «в конечном счете», система достигает согласованности, распространяя и объединяя все изменения от разных пользователей.


Данные на всех узлах рано или поздно становятся одинаковыми.

  • Гибкие уровни согласованности – например, «читаем свежие данные, если возможно».
  • Механизмы Gossip Protocol – узлы обмениваются информацией о последних изменениях.
  • Read Repair – если запрос вернул устаревшие данные, база может их обновить в фоновом режиме.

Пример:

  • Cassandra использует hinted handoff (хранит «подсказки» для недоступных узлов и передаёт их позже).
  • DynamoDB применяет vector clocks (временные метки для согласования версий данных).

Краткое описание различий между ACID и BASE

Теорема CAP (Consistency, Availability, Partition Tolerance)

В мире распределённых баз данных ключевую роль играет теорема CAP (Consistency, Availability, Partition Tolerance), предложенная Эриком Брюэром (Eric Brewer) в 2000 году.

Теорема CAP в информатике гласит, что распределенное хранилище данных не может предоставить более двух из трех следующих гарантий:

  • C – Consistency (Согласованность): каждое чтение получает самую последнюю запись или ошибку. Все узлы видят одни и те же данные в одно и то же время.
  • A – Availability (Доступность): каждый запрос получает ответ (без ошибок), без гарантии, что он содержит самую последнюю запись. Система отвечает на запросы даже при сбоях, но может выдавать устаревшие данные.
  • P – Partition Tolerance (Устойчивость к разделению сети): система продолжает работать, несмотря на произвольное количество сообщений, удаленных (или задержанных) сетью между узлами. Система продолжает работать, даже если сеть между узлами разорвана.

Главный вывод теоремы CAP: в случае сетевых проблем (P) база данных должна выбрать между строгой согласованностью (C) или доступностью (A).


CAP теорема указывает, что распределенная система может иметь максимум два свойства из трех одновременно:

  1. Согласованность (атомарность) — Каждая операция чтения, должна возвращать значение, установленное в последней операции записи: то есть у каждого узла есть актуальные данные о определенном объекте (или данные во всех узлах не противоречат друг другу).
  2. Доступность — Каждый запрос, полученный исправным узлом, влечет за собой ответ. Изначально было что: «почти все запросы должны получать ответы». Отсутствие ответа — неответ по таймауту, и все ошибки формата «сервер занят».
  3. Устойчивость к распределению: Кластер сохраняет работоспособность при условии потери произвольного количества сообщений, посылаемых между узлами сети. Распределение означает, что все пакеты от узлов одной партиции не доходят до узлов другой партиции.

В 2002 году Сет Джилберт и Нэнси Линч из Массачусетского технологического института подобрали формальные модели асинхронных и синхронных распределённых вычислений, в рамках которых показано выполнение теоремы CAP в условиях отсутствия синхронизации (общих часов) у узлов распределённой системы и принципиальную возможность компромисса в частично синхронных системах. В этой работе «согласованность» в смысле теоремы CAP соотнесена с выполнением первых двух требований ACID — атомарности и согласованности. В дальнейшем, многие практики ссылались на данную работу как на доказательство теоремы CAP.

Как теорема CAP влияет на выбор баз данных?

Распределённые базы данных выбирают две из трёх характеристик:

  • CP (Consistency + Partition Tolerance)
    • Строгая согласованность важнее доступности (во время сетевых проблем система может отказать в обслуживании)
    • Если важны точные, актуальные данные (банковские транзакции, финансовые операции).
    • Примеры СУБД: MongoDB (с Strong Consistency), HBase, Zookeeper
  • AP (Availability + Partition Tolerance)
    • Доступность важнее строгой согласованности (временно возможны устаревшие данные)
    • Если важнее всегда получать ответ, даже если данные могут быть устаревшими (соцсети, системы логирования)
    • Cassandra, DynamoDB, Riak
  • CA (Consistency + Availability)
    • Теоретически невозможна в распределённых системах, потому что сеть всегда может дать сбой
    • В реальном мире сеть не идеальна, поэтому отказоустойчивость (P) нельзя игнорировать.
      Если сеть рвётся, приходится жертвовать либо C, либо A.
    • Реляционные базы в локальной сети (PostgreSQL, MySQL, MSSQL в монолитной архитектуре)

Теорема CAP в отношении ACID и BASE

  • ACID (Atomicity, Consistency, Isolation, Durability) – это не противоречие CAP, а подход для локальных транзакций.
  • BASE (Basically Available, Soft State, Eventually Consistent) – модель NoSQL, строится вокруг AP-решений из CAP.

В реальности все системы балансируют между CAP, BASE и ACID, используя кванты согласованности и кэширование.


В чем разница между базами данных ACID и BASE?

Аббревиатуры BASE и ACID специально подбирались так, чтобы в английском языке они противопоставлялись друг другу, поскольку эти же слова обозначают химически противоположные термины «щелочь» и «кислота».


ACID и BASE – это модели транзакций для баз данных, которые определяют структуру данных и порядок работы с ними в базе данных. В контексте баз данных транзакцией называют любую операцию, которую база данных обрабатывает как единую единицу работы. Чтобы база данных оставалась согласованной, транзакция должна быть полностью завершена. Например, если вы переводите деньги с одного банковского счета на другой, нужно отразить эти изменения и на вашем счете, и на счете получателя. Такую транзакцию невозможно считать завершенной без выполнения обоих шагов.

В базах данных ACID приоритет отдается согласованности в ущерб доступности. Если на любом этапе транзакции возникает ошибка, вся транзакция полностью отменяется. Напротив, базы данных BASE отдают приоритет доступности в ущерб согласованности. При неудачном завершении транзакции пользователи могут временно получать несогласованные данные. Согласованность данных восстанавливается с некоторой задержкой.

Для чего важны ACID и BASE?

Например, когда покупатель добавляет товар в корзину на веб-сайте электронной коммерции, все остальные покупатели должны увидеть снижение уровня запасов этого товара. Если очередной покупатель добавит в корзину последний экземпляр, все остальные пользователи должны увидеть, что товара нет в наличии. Разработчикам баз данных нужно сделать выбор о поведении базы данных в том случае, если какая-либо операция в транзакции не может быть выполнена. База данных может действовать по одному из следующих принципов.

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

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

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

Может ли база данных быть одновременно ACID и BASE?

Согласно теореме CAP, база данных может удовлетворять только двум из трех требований: согласованность, доступность и устойчивость к разделению. Обе модели баз данных ACID и BASE обеспечивают устойчивость к разделению, то есть не могут быть одновременно высокосогласованными и постоянно доступными. Это означает, что любая база данных может больше или меньше соответствовать концепции ACID или BASE, но не может использовать оба подхода одновременно. Например, базы данных SQL структурированы по модели ACID, а базы данных NoSQL используют архитектуру BASE. Некоторые базы данных NoSQL могут обладать определенными свойствами, характерными для ACID, но никогда не могут полностью соответствовать концепции ACID.

Когда что использовать: ACID в сравнении с BASE

Несмотря на существенные различия, системы баз данных ACID и BASE применяются в разных приложениях. ACID идеально подходит для корпоративных приложений, в которых требуются согласованность, надежность и предсказуемость данных. Например, банки всегда используют для хранения транзакций клиентов базу данных с архитектурой ACID, поскольку целостность данных здесь является главным приоритетом. В свою очередь, базы данных BASE лучше подходят для аналитической обработки слабо структурированных данных в больших объемах. Например, веб-сайты электронной коммерции используют базы данных с архитектурой BASE для хранения цен на товары, которые часто меняются. В этом случае точность отображения цен менее важна, чем своевременное информирование клиентов об изменении цены.

Ключевые различия между ACID и BASE

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

Масштабирование

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

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

Гибкость

Базы данных ACID менее гибки в обработке данных. Такая база данных должна гарантировать немедленную согласованность, поэтому она может ограничивать доступ к некоторым приложениям в случае сбоев в сети или в электроснабжении. Аналогичным образом, приложениям приходится ждать своей очереди на обновление данных, если другие программные модули уже обрабатывают некоторую запись. Базы данных BASE намного более гибкие. В архитектуре BASE не используются строгие ограничения, и приложения могут изменять записи по мере появления обновлений.

Производительность

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

Напротив, к базе данных BASE приложения могут обращаться для обработки записей в любое время. Это позволяет избежать длительного времени ожидания и повышает пропускную способность базы данных.

Синхронизация

База данных с архитектурой ACID нуждается в механизме синхронизации, чтобы выполненные в транзакции изменения были зафиксированы одновременно во всех связанных записях. В то же время, каждая изменяемая запись должны быть заблокирована от доступа других сторон до завершения или отмены транзакции. База данных BASE, в свою очередь, работает без блокировки записей и поддерживает только согласованность «в конечном счете», без каких-либо гарантий по времени ее достижения. При работе с базами данных BASE разработчики понимают, что при обработке записей могут и будут возникать несоответствия, и принимают необходимые меры предосторожности в самом приложении.

Колоночные базы данных

ClickHouse, Vertica, Teradata – это колонночные базы данных, предназначенные для аналитики и обработки больших данных (Big Data). Они не совсем NoSQL, но и не классические реляционные базы, потому что работают по другой модели, ориентированной на быструю агрегацию и аналитические запросы.

Как они работают?

  • Колонночное хранение – данные хранятся не построчно (как в классических реляционных БД), а по колонкам. Это ускоряет агрегатные операции (SUM, AVG, COUNT).
  • Массовая параллельная обработка (MPP — Massively Parallel Processing) – база распределяет нагрузку между узлами кластера, что ускоряет вычисления.
  • Жесткая схема – в отличие от NoSQL, эти базы обычно требуют заранее заданной структуры данных.

ACID или BASE?

Эти системы не используют ни чистый ACID, ни BASE, а скорее компромиссный подход:

База данныхМодель согласованностиДоступностьТранзакции
ClickHouseEventual Consistency (не гарантирует строгую ACID-согласованность, данные могут быть «размазанными» в кластере)Высокая (оптимизирована для чтения)Поддерживает «атомарные» вставки, но нет полноценной поддержки ACID
VerticaStrong Consistency (более строгая согласованность, чем ClickHouse)Высокая, но зависит от кластераОграниченная поддержка транзакций
TeradataStrong Consistency (ACID-like)Высокая, но заточена под масштабируемостьПоддерживает транзакции, но основное назначение – аналитика

Они ближе к Eventual Consistency (Окончательная согласованность), но не совсем BASE и не ACID. Они оптимизированы под скорость аналитики, жертвуя полной транзакционной поддержкой (как в ACID) ради высокой производительности.

А как работает GreenPlum?

Greenplum – это масштабируемая MPP (Massively Parallel Processing) реляционная СУБД, основанная на PostgreSQL. Она предназначена для аналитических задач и хранилищ данных (DWH – Data Warehouse).

  • Тип: Колонно-строчная реляционная СУБД (по структуре ближе к классическим РСУБД, но заточена под аналитику).
  • Используемая модель: ACID для отдельных сегментов, но в целом ориентирована на MPP-анализ (компромисс между ACID и Eventual Consistency).
  • Область применения: Big Data, хранилища данных, аналитические запросы (OLAP).

Greenplum – это гибрид между классической ACID-реляционной СУБД (PostgreSQL) и MPP-анализом больших данных.


Как работает Greenplum?

  • Massively Parallel Processing (MPP) – база данных делится на узлы (Data Nodes), каждый из которых выполняет свою часть запроса параллельно.
  • Segment-based Architecture – данные хранятся в разделах (сегментах), а главный узел (Master) управляет запросами.
  • ACID внутри сегментов – каждая нода гарантирует ACID на своем уровне, но согласованность между узлами достигается за счёт распределенных транзакций.
  • Ориентация на аналитические запросы (OLAP) – поддержка SQL, индексов, распределённой агрегации.

По модели – не совсем ACID и не BASE, а гибрид ACID + MPP, где каждый сегмент ACID, но согласованность распределённых транзакций не моментальная.

Использованные ссылки для написания статьи

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x