MongoDB: многопроцессорное обновление и операция '$ inc' - PullRequest
0 голосов
/ 11 октября 2018

У меня есть вопрос о одновременном обновлении $inc в MongoDB.На странице справочника UpdateOne и findOneAndUpdate была упомянута тонкость применения одновременного удаления, и всегда рекомендуется использовать уникальный индекс для сопоставления обновлений.Основная идея заключается в том, что если два процесса пытаются обновить определенный документ, который не существует, и один из них завершил выполнение запроса, прежде чем другой выполнит операцию восстановления, то без уникального индекса каждый процесс создаст новый документ, что приведет к дублированию.В этом случае действительно определение уникального индекса предотвратит это.

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

{'name': 'Alice', 'votes': 0}, 
{'name': 'Bob', 'votes': 0}
...

Допустим, name был уникально проиндексирован (при условии отсутствия кандидатов с таким именем).Предположим, что многие процессы собирают голосования и выполняют следующее обновление:

collection.update_one({'name': name}, {'$inc': {'votes': 1}}, upsert=False)

, где name - это, скажем, переменная python, определенная где-то еще.Интересно, может ли здесь применяться тот же аргумент в руководстве ( см. Пример )?

Представьте себе, что в какой-то момент Алиса получила 5 голосов.Процесс A и процесс B хотят увеличить количество голосов Алисы на 1. Мы ожидаем, что Алиса получит 7 голосов, если оба процесса будут работать правильно.Однако, если процесс A находит документ Алисы после того, как B находит его, но до того, как B начинает делать приращение, тогда процесс A должен знать, что Алиса имеет 5 голосов, так же, как процесс B. Следовательно, даже если A выполнит изменение после Bснимает блокировку записи, она меняет голоса на 5 + 1 = 6 голосов, а не на 7.

Я все понял неправильно?Я думаю, что это как-то связано с тем, как $inc и как на самом деле работает обновление одного документа, но я не уверен, потому что:

  1. эта часть информации не кажетсячтобы быть упомянутым на $inc странице справочника и

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

Любое понимание того, как поиск и обновление работает с updateOne и findOneAndUpdate, и как работает операция $inc, приветствуется.

Cheers!

1 Ответ

0 голосов
/ 11 октября 2018

Для чтения и записи понимания, вам необходимо понять блокировку Механизм в MongoDB.

Запуск в MongoDB 3.2,механизм хранения WiredTiger является механизмом хранения по умолчанию.

Essentials

Механизм хранения WiredTiger переносит блокировку на уровне документа в MongoDB, что означает отсутствие записибольше блокировать коллекцию или базу данных.В то время как MMAP в 3.0 принес блокировку на уровне коллекции, многократные записи в одну и ту же коллекцию по-прежнему будут приводить к тому, что записи будут применяться последовательно и могут голодать чтения из коллекции, так как чтения должны ждать окончания записи.WiredTiger избавляется от ограничения, позволяющего выполнять несколько записей одновременно для одной и той же коллекции.Это означает, что запись и чтение масштабируются с помощью ЦП, тогда как в MMAP был низкий потолок для масштабирования ЦП, поскольку блокировки снижали пропускную способность.

Согласно Механизм хранения WiredTiger

после поступления запроса на запись все считыватели блокируются до завершения записи для определенной коллекции.

Ссылочная ссылка: 1. OverviewLink ,2. aboutStorageEngin

поведение findAndModify

Upsert and Unique Index

Когда команда findAndModify включает в себя параметр upsert: true и поле запроса (s) не индексируется однозначно, команда может вставлять документ несколько раз при определенных обстоятельствах.

Чтобы предотвратить создание нескольких дубликатов документов, создайте уникальный индекс в поле имени.При наличии уникального индекса несколько команд findAndModify будут демонстрировать одно из следующих действий:

Ровно один findAndModify успешно вставляет новый документ.Ноль или более команд findAndModify обновляют вновь вставленный документ.Ноль или более команд findAndModify завершаются неудачно, когда они пытаются вставить дубликат.Если команда не выполнена из-за нарушения уникального ограничения индекса, вы можете повторить команду.При удалении документа повторная попытка не должна завершиться.

ссылка Ссылка: здесь

...