Что в действительности означало, что MongoDB не соответствует требованиям ACID до v4?

226

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

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

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

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

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

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

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

Лэнс Поллард
источник

Ответы:

133

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

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

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

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

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

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

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

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

Брайан Мильориси
источник
27
« Атомные модификаторы в MongoDB могут работать только против одной коллекции » => Я думаю, что вы имели в виду «против одного документа ».
assylias
2
Отличная информация, как правило, отличный ответ за исключением предложения использовать MySQL.
Дуг Молинью
״ Одна вещь, которую вы теряете с MongoDB - это транзакции с несколькими коллекциями (таблицами). Атомные модификаторы в MongoDB могут работать только с одним документом ״ из mongo doc ( docs.mongodb.com/v3.2/core/write-operations-atomicity ): «В MongoDB операция записи является атомарной на уровне одного документ, даже если операция изменяет несколько встроенных документов в одном документе. "
yoav.str
5
Отсутствие транзакций ACID с несколькими документами больше не имеет место. MongoDB объявили, что они появятся в v4.0. См. Mongodb.com/blog/post/multi-document-transactions-in-mongodb
Григорий Мельник,
1
На данный момент, поскольку MongoDB 4.0 совместим с ACID mongodb.com/transactions с многодокументными транзакциями. Посмотрите на mongodb.com/blog/post/...
ратах
134

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

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

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

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

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

Уильям З
источник
3
Обратите внимание, что транзакции двухфазных фиксаций не совместимы с ACID. По какой-то причине я сделал вывод обратное, пока не перешел по ссылке.
Джастин C
1
Возникает вопрос о долговечности распределенной MongoDB на уровне документов, независимо от конфигурации записи. Инструмент с открытым исходным кодом Jepsen обнаружил, что данные могут быть потеряны из-за сетевого раздела даже с проблемой записи MAJORITY. Смотрите статью
jrullmann
9
Наличие ACID на уровне одного документа, который в некотором роде эквивалентен отдельной записи в СУБД, во многих случаях бесполезен. Срок транзакции не относится к одной таблице, и вы даже можете иметь механизм двухфазной фиксации и задействовать несколько XAResource, поэтому ссылаться на один документ как на ACID-совместимый довольно проблематично, ИМХО.
Яир Заславский
5
Согласен с Яир. «ACID-совместимый на уровне документа» не является пунктом продажи. Это в основном означает «не соответствует требованиям ACID». ACID никогда не предназначался для "только одной строки / документа / объекта". Речь идет о сохранении согласованности ваших данных по всей базе данных.
joshua.paling
34

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

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

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

duffymo
источник
1
Как и любая аналогия, она имеет свои ограничения. В программном обеспечении легко создавать новые массивы [кассиры] и заставлять их обрабатывать синхронные транзакции каждая, в то время как реальные затраты на это будут смехотворно высокими.
HRJ
16

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

подзатворного
источник
1
спасибо @subGate. Кто-нибудь, кто может поделиться своим опытом с ravenDB и действительно ли он удовлетворяет требованию?
Nir Pengas
12

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

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

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

Сергей
источник
10

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

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

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

Григорий Мельник
источник
Вышел первый кандидат на выпуск MongoDB4.0 - linkedin.com/pulse/mongodb-40-rc0-now-available-grigori-melnik
Григорий Мельник
5

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

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

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

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

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

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

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

Ely
источник
4

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

joeshmoe
источник
Не могли бы вы объяснить, почему это увеличивает параллелизм? Извините, если я упускаю очевидное здесь.
Батбрат
@batbrat: рассмотрим двух клиентов, которые пытаются одновременно писать в разные коллекции в одной базе данных. При блокировке базы данных один из клиентов должен будет дождаться завершения работы другого, прежде чем произойдет его запись. С блокировкой коллекции оба клиента могут писать одновременно. Вот что подразумевается под повышенным параллелизмом. Конечно, если оба клиента пытаются записать в одну и ту же коллекцию, нужно будет подождать.
Jrullmann
2

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

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

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

Хотя есть несколько ограничений на то, как и какие операции можно выполнять.

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

Mysterious25K
источник
1

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

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

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

Рысцов
источник