У меня есть вопрос о одновременном обновлении $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
и как на самом деле работает обновление одного документа, но я не уверен, потому что:
эта часть информации не кажетсячтобы быть упомянутым на $inc
странице справочника и
, нелегко спланировать эксперимент для этого, так как для того, чтобы два процесса столкнулись, необходимо иметь большой набор данных.Для небольшого набора данных одному процессу слишком просто найти нужный документ и изменить его до того, как появится другой процесс.На самом деле, я провел эксперимент по голосованию двух кандидатов, и ничего не пошло не так, независимо от того, уникально ли внесено имя или нет.
Любое понимание того, как поиск и обновление работает с updateOne
и findOneAndUpdate
, и как работает операция $inc
, приветствуется.
Cheers!