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

184

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

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

Но когда я вхожу в разговоры о 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 для этого, и др.).

Теги:
database
nosql
acid

8 ответов

102
Лучший ответ

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

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

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

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

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

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

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

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

  • 25
    « Атомные модификаторы в MongoDB могут работать только против одной коллекции » => Я думаю, что вы имели в виду «против одного документа ».
  • 1
    Отличная информация, как правило, отличный ответ за исключением предложения использовать MySQL.
Показать ещё 3 комментария
103

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

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

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

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

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

  • 3
    Был самый ясный ответ для меня
  • 3
    Обратите внимание, что транзакции двухфазных фиксаций не совместимы с ACID. По какой-то причине я сделал вывод обратное, пока не перешел по ссылке.
Показать ещё 3 комментария
31

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

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

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

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

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

  • 1
    спасибо @subGate. Кто-нибудь, кто может поделиться своим опытом с ravenDB и действительно ли он удовлетворяет требованию?
11

"не будет корректно сохранено" может означать:

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

  • Нет простых "атомных" обновлений для нескольких коллекций и даже нескольких документов в одной коллекции. Это не проблема в большинстве случаев, потому что ее можно обойти с помощью Two Phase Commit или реструктурировать вашу схему, чтобы обновления были сделаны в один документ. См. Этот вопрос: Базы данных документов: избыточные данные, ссылки и т.д. (Особенно MongoDB)

5

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

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

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

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

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

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

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

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

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

1

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню