Что в действительности означало, что MongoDB не соответствует требованиям ACID до версии v4? - PullRequest
220 голосов
/ 22 августа 2011

Я не эксперт по базам данных и не имею официального образования в области компьютерных наук, так что терпите меня.Я хочу знать, какие виды реального мира могут произойти, если вы используете старую версию MongoDB до v4 , которая не была совместима с ACID .Это относится к любой базе данных, несовместимой с ACID.

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

Но когда я захожу в разговоры о MongoDB, те из нас, кто не знает технических деталей о том, как на самом деле реализуются базы данных, начинают разбрасываться такими заявлениями:

MongoDB намного быстрее, чем MySQL и Postgres, но есть небольшой шанс, например, 1 на миллион, что он "не сохранится правильно".

Это "победило"«Правильное сохранение» - это относится к следующему пониманию: если в момент записи в MongoDB происходит сбой питания, есть шанс для конкретной записи (скажем, вы отслеживаете просмотры страниц в документах с 10 атрибутами каждый), чтоодин из документов сохранил только 5 атрибутов ... что означает, что со временем ваша страницаСчетчики ew будут «слегка» выключены.Вы никогда не узнаете, насколько, вы знаете, что они будут правильными на 99,999%, но не на 100%.Это потому, что, если вы специально не сделали эту атомарную операцию mongodb , эта операция не гарантированно была атомарной.

Поэтому мой вопрос заключается в том, как правильно интерпретировать, когда и почемуMongoDB не может "сохранить правильно"?Каким частям ACID он не соответствует, и при каких обстоятельствах, и как вы узнаете, что эти 0,001% ваших данных не соответствуют?Разве это не может быть исправлено как-то?Если нет, то это означает, что вы не должны хранить такие вещи, как ваша таблица users в MongoDB, потому что запись может не сохраниться.Но опять же, этому 1/1 000 000 пользователей, возможно, просто нужно «попробовать зарегистрироваться заново», не так ли?

Я просто ищу, может быть, список того, когда / почему происходят негативные события с несовместимой с ACID базой данных, такой как MongoDBи в идеале, если есть стандартный обходной путь (например, запустить фоновое задание для очистки данных или использовать только SQL для этого и т. д.).

Ответы [ 10 ]

131 голосов
/ 06 июля 2013

На самом деле неправильно, что MongoDB не совместим с ACID.Напротив, MongoDB является ACID-совместимым на уровне документа .

Любое обновление для одного документа:

  • Атомное: либо полностью завершено, либо нет
  • Согласовано: ни один читатель не увидит «частично примененное» обновление
  • Изолированный: снова ни один читатель не увидит «грязное» чтение
  • Durable: (с соответствующей записью)

То, что MongoDB не имеет, транзакции - то есть обновления нескольких документов, которые можно откатить и совместимы с ACID.

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

129 голосов
/ 22 августа 2011

Одна вещь, которую вы теряете с MongoDB - это множественные (табличные) транзакции. Атомные модификаторы в MongoDB могут работать только против одного документа.

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

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

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

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

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

2) Использовать транзакционную базу данных совместно с MongoDB. Обычно MySQL используется для предоставления транзакций для вещей, которые им абсолютно необходимы, при этом позволяя MongoDB (или любому другому NoSQL) делать то, что он делает лучше всего.

Если мое решение из # 1 не будет работать в долгосрочной перспективе, я продолжу изучение возможности объединения MongoDB с MySQL, но пока # 1 хорошо подходит для моих нужд.

34 голосов
/ 22 августа 2011

Хорошее объяснение содержится в "Starbucks не использует двухфазную фиксацию" .

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

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

16 голосов
/ 28 февраля 2013

Я думаю, что другие люди уже дали хорошие ответы.Однако я хотел бы добавить, что существуют БД ACID NOSQL (например, http://ravendb.net/).Так что это не только решение NOSQL - нет ACID vs Relational с ACID ....

12 голосов
/ 01 сентября 2011

«не сохранится правильно» может означать:

  1. По умолчанию MongoDB не сохраняет ваши изменения на диск немедленно.Таким образом, существует вероятность, что вы сообщаете пользователю «обновление прошло успешно», происходит сбой питания и обновление теряется.MongoDB предоставляет опции для контроля уровня обновления «долговечность».Он может подождать, пока другие реплики получат это обновление (в памяти), подождать, пока произойдет запись в файл локального журнала и т. Д.атомарные »обновления для нескольких коллекций и даже нескольких документов в одной коллекции.В большинстве случаев это не проблема, поскольку ее можно обойти с помощью Two Phase Commit или реструктурировать вашу схему, чтобы обновления выполнялись в одном документе.См. Этот вопрос: Базы данных документов: избыточные данные, ссылки и т. Д. (В частности, MongoDB)

9 голосов
/ 18 февраля 2018

Начиная с MongoDB v4.0, должны поддерживаться многодокументные транзакции ACID. Благодаря изоляции моментальных снимков транзакции обеспечат глобально согласованное представление данных и обеспечат выполнение «все или ничего» для обеспечения целостности данных.

Они чувствуют себя как транзакции из реляционного мира, например ::1003

with client.start_session() as s:
    s.start_transaction()
    try:
        collection.insert_one(doc1, session=s)
        collection.insert_one(doc2, session=s)
        s.commit_transaction()
    except Exception:
        s.abort_transaction()

См. https://www.mongodb.com/blog/post/multi-document-transactions-in-mongodb

4 голосов
/ 09 мая 2015

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

Также в документации MongoDB вы можете найти вопрос и ответ .

MongoDB не совместим с ACID.Читайте ниже для обсуждения соответствия ACID.

  1. MongoDB A томичен только на уровне документа.Он не соответствует определению Atomic, которое мы знаем из систем реляционных баз данных, в частности, по ссылке выше.В этом смысле MongoDB не соответствует A из ACID.
  2. MongoDB по умолчанию C. Однако вы можете читать со вторичных серверов в наборе реплик.В этом случае вы можете иметь только согласованность .Это полезно, если вы не возражаете читать немного устаревшие данные.
  3. MongoDB не гарантирует I засоления (опять же согласно приведенному выше определению):
  1. Для систем с несколькими одновременными программами чтения и записи MongoDB позволит клиентам читать результаты операции записи до того, как операция записи завершится.
  2. Если mongod завершается до фиксации журнала, даже если запись успешно завершаетсязапросы могут иметь данные, которые не будут существовать после перезапуска mongod.

Однако , MongoDB изменяет каждый документ изолированно (для вставок и обновлений);только на уровне документа, но не для многодокументных транзакций.

В отношении D urability - вы можете настроить это поведение с опцией write concern, хотя не уверен.Может быть, кто-то знает лучше.

Я полагаю, что продолжаются некоторые исследования для продвижения NoSQL к ограничениям ACID или аналогичным.Это сложная задача, поскольку базы данных NoSQL обычно бывают быстрыми (er), а ограничения ACID могут значительно снизить производительность.

4 голосов
/ 17 апреля 2013

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

2 голосов
/ 01 сентября 2018

«В MongoDB операция над одним документом является атомарной» - Это то, что нужно в прошлом

В новой версии MongoDB 4.0 вы МОЖЕТЕ:

Однако в ситуациях, когда требуется обновить атомарность для обновлений нескольких документов или согласованность между чтениями нескольких документов, MongoDB предоставляет возможность выполнять транзакции с несколькими документами для наборов реплик. Многодокументные транзакции могут использоваться в нескольких операциях, коллекциях, базах данных и документах. Многодокументные транзакции обеспечивают предложение «все или ничего». Когда транзакция фиксируется, все изменения данных, сделанные в транзакции, сохраняются. Если какая-либо операция в транзакции завершается неудачей, транзакция прерывается, и все изменения данных, сделанные в транзакции, отбрасываются, не становясь видимыми. Пока транзакция не зафиксирована, никакие операции записи в транзакции не видны вне транзакции.

Хотя есть несколько ограничений для Как и Какие операции могут быть выполнены.

Проверьте Монго Док. https://docs.mongodb.com/master/core/transactions/

1 голос
/ 04 марта 2016

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

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

Если вы согласны с уровнем изоляции для фиксации чтения, то имеет смысл взглянуть на транзакции RAMP Питера Бейлиса. Они также могут быть реализованы для MongoDB на стороне клиента.

...