Введение

Набор свойств транзакций базы данных

В информатике ACID (атомарность, согласованность, изолированность, долговечность) — это набор свойств транзакций базы данных, предназначенных для гарантии достоверности данных, несмотря на ошибки, сбои питания и другие непредвиденные обстоятельства. В контексте баз данных, последовательность операций базы данных, удовлетворяющая свойствам ACID (которая может восприниматься как единая логическая операция с данными), называется транзакцией. Например, перевод средств с одного банковского счета на другой, даже включающий несколько изменений, таких как списание средств с одного счета и зачисление на другой, является единой транзакцией. В 1983 году Андреас Рейтер и Тео Хердер предложили акроним ACID, опираясь на более ранние работы Джима Грея, который определил атомарность, согласованность и долговечность, но не изолированность, при описании концепции транзакции. Эти четыре свойства являются основными гарантиями транзакционной парадигмы, оказавшей влияние на многие аспекты разработки систем управления базами данных. По словам Грея и Рейтера, система управления информацией IBM поддерживала транзакции ACID уже в 1973 году (хотя акроним был создан позднее).

Атомность

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

Последовательность

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

Изоляция

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

Прочность

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

Примеры

Следующие примеры дополнительно иллюстрируют свойства ACID. В этих примерах таблица базы данных имеет два столбца, A и B. Ограничение целостности требует, чтобы значение в столбце A и значение в столбце B в сумме давали 100. Следующий SQL-код создает таблицу, описанную выше: CREATE TABLE acidtest (A INTEGER, B INTEGER, CHECK (A + B = 100));

Атомность

Атомичность – это гарантия того, что серия операций базы данных в рамках атомарной транзакции либо будет выполнена целиком (успешное выполнение), либо не будет выполнена вовсе (неуспешное выполнение). Серию операций нельзя разделить так, чтобы были выполнены лишь некоторые из них, что делает эту серию "неделимой". Гарантия атомичности предотвращает частичное обновление базы данных, что может привести к более серьезным проблемам, чем отклонение всей транзакции целиком. Иными словами, атомичность означает неделимость и неразложимость. В качестве альтернативы можно сказать, что логическая транзакция может состоять из нескольких физических транзакций. Логическая транзакция считается завершенной только после успешного выполнения всех составляющих ее физических транзакций. Примером атомарной транзакции является денежный перевод с банковского счета А на счет Б. Она состоит из двух операций: списание средств со счета А и зачисление средств на счет Б. Мы не хотим, чтобы средства были списаны со счета А, пока не убедимся, что они успешно зачислены на счет Б. Выполнение этих операций в рамках атомарной транзакции гарантирует, что база данных останется в согласованном состоянии, то есть деньги не будут списаны или зачислены, если хотя бы одна из этих двух операций завершится неудачей.

Недостаток согласованности

Последовательность – это очень общий термин, который требует, чтобы данные соответствовали всем правилам валидации. В предыдущем примере валидация подразумевает, что все правила валидации должны быть проверены для обеспечения согласованности. Предположим, транзакция пытается вычесть 10 из значения, не изменяя его. Поскольку согласованность проверяется после каждой транзакции, известно, что значение до начала транзакции. Если транзакция успешно вычитает 10 из этого значения, будет достигнута атомарность. Однако проверка валидации покажет, что результат, что не соответствует правилам базы данных. Вся транзакция должна быть отменена, а затронутые строки возвращены в состояние, предшествующее транзакции. Если бы существовали другие ограничения, триггеры или каскадные обновления, каждая операция изменения была бы проверена таким же образом, как описано выше, перед фиксацией транзакции. Подобные проблемы могут возникать и с другими ограничениями. Например, мы могли бы потребовать, чтобы типы данных и были целыми числами. Если мы попытаемся ввести, скажем, значение 13,5 для , транзакция будет отменена, или система может сгенерировать оповещение в виде триггера (если такой триггер был настроен). Другим примером являются ограничения целостности, которые не позволяют удалять строку из одной таблицы, если её первичный ключ используется хотя бы одним внешним ключом в других таблицах.

Недостаток долговечности

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

Реализация

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

Закрытие против многоверсионного

Многие базы данных используют блокировки для обеспечения свойств ACID. Блокировка означает, что транзакция помечает данные, к которым она обращается, чтобы СУБД знала, что не должна разрешать другим транзакциям их изменять до тех пор, пока первая транзакция успешно не завершится или не будет отменена. Блокировка всегда должна быть получена перед обработкой данных, включая данные, которые только читаются, но не изменяются. Нетривиальные транзакции обычно требуют большого количества блокировок, что приводит к существенным накладным расходам и блокированию других транзакций. Например, если пользователь A выполняет транзакцию, которая должна прочитать строку данных, которую пользователь B хочет изменить, пользователь B должен ждать завершения транзакции пользователя A. Двухфазная блокировка часто применяется для гарантии полной изоляции. Альтернативой блокировке является многоверсионное управление параллелизмом, при котором база данных предоставляет каждой читающей транзакции предыдущую, неизмененную версию данных, изменяемую другой активной транзакцией. Это позволяет читателям работать без получения блокировок, то есть записывающие транзакции не блокируют читающие транзакции, а читатели не блокируют записывающих. Вернемся к примеру: когда транзакция пользователя A запрашивает данные, которые изменяет пользователь B, база данных предоставляет A версию этих данных, которая существовала на момент начала транзакции пользователя B. Пользователь A получает согласованное представление базы данных, даже если другие пользователи изменяют данные. Одна из реализаций, известная как изоляция снимков, ослабляет свойство изоляции.

Распределенные операции

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