Насколько много маркетинга в ACID?
Всем привет. На связи Владислав Родин. В настоящее время я являюсь руководителем курса «Архитектор высоких нагрузок» в OTUS, а также преподаю на курсах, посвященных архитектуре ПО.
Помимо преподавания, как вы могли заметить, я занимаюсь написанием авторского материала для блога OTUS на хабре и сегодняшнюю статью хочу приурочить к запуску курса «Базы данных», на который прямо сейчас открыт набор.
Транзакции появились в 70-ых годах и были представлены в качестве инструмента базы данных, позволяющего решить проблемы отказоустойчивости и доступа к данным в конкурентной среде. Затем был сформулирован ряд свойств, которыми должна обладать транзакция для того, чтобы выполнять поставленные перед ней задачи, а заглавные буквы этих свойств, поставленные в нужном порядке, составили красивую аббревиатуру ACID.
Период времени, в течении которого происходили данные события, характеризовался отсутствием высоких нагрузок, Интернета и проблем с производительностью, для решения которых можно было обойтись лишь методами вертикального масштабирования. Впоследствии, в начале 2000-ых возник тренд на NoSQL базы данных, появилась аббревиатура BASE, которая фактически противопоставлялась классическому ACID (ACID — кислота, BASE — щелочь). Сейчас возникает обратный тренд на ACID. Даже NoSQL-ая MongoDB стала поддерживать ACID.
Давайте разберемся с тем, что означает данная аббревиатура и насколько много маркетинга в ней.
ACID представляет 4 свойства:
A = atomicity (атомарность)
C = consistency (консистентность или целостность)
I = isolation (изоляция)
D = durability (надежность)
А теперь давайте поговорим о каждом свойстве отдельно.
Атомарность является перегруженным термином и в контексте транзакций в базе данных может быть сформулирована в виде принципа «все или ничего». Если ваша транзакция содержит в себе 10 операций insert, то будут выполнены либо все 10 (будет осуществлен commit транзакции), либо ни один из них (будет осуществлен rollback транзакции).
Каким образом обеспечивается данное свойство? Дело в том, что когда в базу приходит транзакция, содержащая те самые 10 insert'ов, данные не начинают изменяться. Транзакция перед накатом непосредственно на данные пишется в журнал, в котором фиксируются изменения, вносимые ею. Данный журнал может быть использован также и для репликации данных, а может быть совершенно с ней не связан, о чем рассказано мною, например, здесь. Благодаря этому журналу может быть осуществлен commit транзакции непосредственно на данные, либо, в случае чего, rollback ее же. Правило, согласно которому транзакцию следует закрывать как можно скорее, следует непосредственно из понимания принципов реализации данного свойства: зачастую базы запрещают чистить данный журнал пока какая-либо транзакция открыта, поэтому он может забиваться, что, в свою очередь, приводит к весьма неприятным последствиям.
В терминах ACID консиситентность обозначает не тоже самое, что в терминах CAP-теоремы (в теории распределенных систем существует достаточно много степеней этой консистентности). Под консистентностью мы понимаем следующее: некоторые заранее определенные инварианты системы должны выполняться как до, так и после commit'а транзакции. В качестве примеров инвариантов системы могут быть представлены: дебит сходится с кредитом, суммарная ЗП сотрудников не превосходит бюджет, количество сотрудников в компании равна количеству открытых ранее вакансий и т. д. На языке БД это означает всего лишь выполнение всех constraint'ов.
Вопрос про необходимость наличия консистентности на уровне БД является достаточно спорным, ведь наличие constraint'ов может говорить о том, что часть бизнес-логики переехала из приложения на уровень БД, что не является общепризнанно хорошей практикой. В конце концов, приложение может само принимать решение просто не commit'ить невалидные данные. Бытует мнение о том, что консистентность была добавлена лишь для того, чтобы аббревиатура получилась красивой (маркетинг).
Изоляция — это свойство базы данных, позволяющее выполнять параллельные транзакции как последовательные. Ведь никто не запрещает базе данных выполнять одновременно несколько транзакций, надо сделать так, чтобы они не влияли друг на друга, чтобы не возникали аномалии вида race condition. Фактически, именно изоляция решает проблему доступа к данным в конкурентной среде.
Раскрытие понятия изоляции из-за своего объема заслуживает отдельной статьи, потому как именно изоляцию можно назвать сердцем ACID. Цена транзакционности часто сводится к цене обеспечения изоляции, именно поэтому изоляция обладает различными уровнями, каждый из которых предоставляет свой уровень защиты от race condition'ов и несет тот или иной overhead. В полной мере изоляция обеспечивается лишь на уровне serializable, который очень тяжело реализовать и который редко когда нужен.
Durability говорит нам о том, что если транзакция была применена, то она ни в коем случае не должна пропасть. Фактически это означает следующее: если БД ответила, что был совершен commit транзакции, то транзакция была зафиксирована в энергонезависимой памяти. Это означает, что произошел системный вызов fsync, т. е. буфферы были сброшены на жесткий диск, и он ответил ok'ом.
Durability тоже является маркетинговым термином, потому как в полной мере он обеспечен быть не может. Даже если мы отбросим искусственные сценарии «сожжения Земли инопланетянами», после которого вообще не останется никаких баз данных и транзакций, более вероятные, но экстремальные сценарии физического уничтожения конкретного жесткого диска, на котором была зафиксирована транзакция, мы можем вспомнить, что системный вызов fsync гарантирует попадание в контроллер жесткого диска, в котором, в свою очередь, все-таки находится энергозависимый буффер. Время пребывания в нем мало, но не равно 0. Как следствие, если выключить электричество ровно в «нужный» момент, то транзакция все-таки может быть потеряна!
Хоть проблема с fsync'ом и решена в дорогостоящей базе от Oracle, ничто не может защитить нас от проблем, связанных с физическим уничтожением машины. Мы можем всего лишь увеличивать гарантии с использованием бэкапов и репликации.
Несмотря на то, что ACID предоставляет достаточно интересные свойства, такие как атомарность и изоляция, некоторые из данных свойств являются всего лишь маркетингом, и даже известный своей строгостью по сравнению с BASE ACID не обеспечивает в полной мере отсутствие возможностей потерь транзакции, а также влияния результатов выполнения одновременных транзакций друг на друга (изоляцию надо еще настраивать!).
Приглашаем всех желающих на бесплатный урок по теме: «Модель работы с данными в PostgreSQL».
Помимо преподавания, как вы могли заметить, я занимаюсь написанием авторского материала для блога OTUS на хабре и сегодняшнюю статью хочу приурочить к запуску курса «Базы данных», на который прямо сейчас открыт набор.
Предисловие
Транзакции появились в 70-ых годах и были представлены в качестве инструмента базы данных, позволяющего решить проблемы отказоустойчивости и доступа к данным в конкурентной среде. Затем был сформулирован ряд свойств, которыми должна обладать транзакция для того, чтобы выполнять поставленные перед ней задачи, а заглавные буквы этих свойств, поставленные в нужном порядке, составили красивую аббревиатуру ACID.
Период времени, в течении которого происходили данные события, характеризовался отсутствием высоких нагрузок, Интернета и проблем с производительностью, для решения которых можно было обойтись лишь методами вертикального масштабирования. Впоследствии, в начале 2000-ых возник тренд на NoSQL базы данных, появилась аббревиатура BASE, которая фактически противопоставлялась классическому ACID (ACID — кислота, BASE — щелочь). Сейчас возникает обратный тренд на ACID. Даже NoSQL-ая MongoDB стала поддерживать ACID.
Давайте разберемся с тем, что означает данная аббревиатура и насколько много маркетинга в ней.
ACID представляет 4 свойства:
A = atomicity (атомарность)
C = consistency (консистентность или целостность)
I = isolation (изоляция)
D = durability (надежность)
А теперь давайте поговорим о каждом свойстве отдельно.
A = atomicity (атомарность)
Атомарность является перегруженным термином и в контексте транзакций в базе данных может быть сформулирована в виде принципа «все или ничего». Если ваша транзакция содержит в себе 10 операций insert, то будут выполнены либо все 10 (будет осуществлен commit транзакции), либо ни один из них (будет осуществлен rollback транзакции).
Каким образом обеспечивается данное свойство? Дело в том, что когда в базу приходит транзакция, содержащая те самые 10 insert'ов, данные не начинают изменяться. Транзакция перед накатом непосредственно на данные пишется в журнал, в котором фиксируются изменения, вносимые ею. Данный журнал может быть использован также и для репликации данных, а может быть совершенно с ней не связан, о чем рассказано мною, например, здесь. Благодаря этому журналу может быть осуществлен commit транзакции непосредственно на данные, либо, в случае чего, rollback ее же. Правило, согласно которому транзакцию следует закрывать как можно скорее, следует непосредственно из понимания принципов реализации данного свойства: зачастую базы запрещают чистить данный журнал пока какая-либо транзакция открыта, поэтому он может забиваться, что, в свою очередь, приводит к весьма неприятным последствиям.
C = consistency (консистентность или целостность)
В терминах ACID консиситентность обозначает не тоже самое, что в терминах CAP-теоремы (в теории распределенных систем существует достаточно много степеней этой консистентности). Под консистентностью мы понимаем следующее: некоторые заранее определенные инварианты системы должны выполняться как до, так и после commit'а транзакции. В качестве примеров инвариантов системы могут быть представлены: дебит сходится с кредитом, суммарная ЗП сотрудников не превосходит бюджет, количество сотрудников в компании равна количеству открытых ранее вакансий и т. д. На языке БД это означает всего лишь выполнение всех constraint'ов.
Вопрос про необходимость наличия консистентности на уровне БД является достаточно спорным, ведь наличие constraint'ов может говорить о том, что часть бизнес-логики переехала из приложения на уровень БД, что не является общепризнанно хорошей практикой. В конце концов, приложение может само принимать решение просто не commit'ить невалидные данные. Бытует мнение о том, что консистентность была добавлена лишь для того, чтобы аббревиатура получилась красивой (маркетинг).
I = isolation (изоляция)
Изоляция — это свойство базы данных, позволяющее выполнять параллельные транзакции как последовательные. Ведь никто не запрещает базе данных выполнять одновременно несколько транзакций, надо сделать так, чтобы они не влияли друг на друга, чтобы не возникали аномалии вида race condition. Фактически, именно изоляция решает проблему доступа к данным в конкурентной среде.
Раскрытие понятия изоляции из-за своего объема заслуживает отдельной статьи, потому как именно изоляцию можно назвать сердцем ACID. Цена транзакционности часто сводится к цене обеспечения изоляции, именно поэтому изоляция обладает различными уровнями, каждый из которых предоставляет свой уровень защиты от race condition'ов и несет тот или иной overhead. В полной мере изоляция обеспечивается лишь на уровне serializable, который очень тяжело реализовать и который редко когда нужен.
D = durability (надежность)
Durability говорит нам о том, что если транзакция была применена, то она ни в коем случае не должна пропасть. Фактически это означает следующее: если БД ответила, что был совершен commit транзакции, то транзакция была зафиксирована в энергонезависимой памяти. Это означает, что произошел системный вызов fsync, т. е. буфферы были сброшены на жесткий диск, и он ответил ok'ом.
Durability тоже является маркетинговым термином, потому как в полной мере он обеспечен быть не может. Даже если мы отбросим искусственные сценарии «сожжения Земли инопланетянами», после которого вообще не останется никаких баз данных и транзакций, более вероятные, но экстремальные сценарии физического уничтожения конкретного жесткого диска, на котором была зафиксирована транзакция, мы можем вспомнить, что системный вызов fsync гарантирует попадание в контроллер жесткого диска, в котором, в свою очередь, все-таки находится энергозависимый буффер. Время пребывания в нем мало, но не равно 0. Как следствие, если выключить электричество ровно в «нужный» момент, то транзакция все-таки может быть потеряна!
Хоть проблема с fsync'ом и решена в дорогостоящей базе от Oracle, ничто не может защитить нас от проблем, связанных с физическим уничтожением машины. Мы можем всего лишь увеличивать гарантии с использованием бэкапов и репликации.
Выводы
Несмотря на то, что ACID предоставляет достаточно интересные свойства, такие как атомарность и изоляция, некоторые из данных свойств являются всего лишь маркетингом, и даже известный своей строгостью по сравнению с BASE ACID не обеспечивает в полной мере отсутствие возможностей потерь транзакции, а также влияния результатов выполнения одновременных транзакций друг на друга (изоляцию надо еще настраивать!).
Приглашаем всех желающих на бесплатный урок по теме: «Модель работы с данными в PostgreSQL».