1

MongoDB Update 文档中,他们谈到更新操作符是原子的。如果以下查询在同一时刻被调用五次并且 Zugwalt 的声誉从零开始,我希望最终声誉为 5:

db.rep.update({_id: "Zugwalt"}, {$inc: {reputation: 1}});

但是,如果更新查询是这样的呢?

db.rep.update({_id: "Zugwalt", reputation: {$lte: 3}}, {$inc: {reputation: 1}});

声望是否总是只更新 3 次,还是有一些奇怪的比赛条件可能会更多?

我的特殊情况是使用活动用户“声明文档”。我执行类似于以下的查询:

db.myCollection.update({_id: "doc_id", activeUser: {$exists: false}}, {$set: {activeUser: "Zugwalt"}});

理想情况下,如果此查询在同一实例中多次触发,则只有一次更新会导致集合被修改。但是,如果搜索组件在更新时不是原子的,我可以看到一个竞争条件,它首先更新为将 activeUser 设置为一个用户,然后立即设置为另一个用户。

旁注:findAndModify命令具有这种原子性似乎更清楚,但是我不想使用它,因为在我们使用 node-js 驱动程序的经验测试中,在重负载下总体上看起来要慢得多。

4

2 回答 2

3

在 MongoDB 中,更新是原子的。如果不需要取回文档,则不需要使用 findAndModify。

在您给出的场景中,预期的事情将会发生 - 在第一种情况下,声誉最终会是 5,在第二种情况下会是 4。

在您的情况下,只有一个更新会成功设置 activeUser。

这是一个讨论 MongoDB 中的原子操作的链接。

于 2012-06-09T06:50:55.933 回答
0

对于这种情况,您应该使用findAndModify. 它是完全原子的。

像这样的东西:

db.runCommand({findAndModify: 'myCollection',
               query: {_id: "doc_id", activeUser: {$exists: false}},
               update: {$set: {activeUser: "Zugwalt"}}})
于 2012-06-09T00:11:22.963 回答