8

MongoDB 支持原子更新。即我可以确定,当文档更新时,没有其他更新会覆盖我之前的更改。我的问题与查询和更新语句的组合有关,下面显示的示例最好地说明了这一点。

db.foo.update(
{ state : 1, players: { $size: 2 } } , 
{ $push: { players : { new player document } } }, 
false , true );

在上面的例子中,如果玩家数量等于 2,我只想将一个新玩家推送到一个玩家集合中。鉴于上面的查询和更新语句,是否有可能两个同时更新都将一个玩家推送到同一个文档, 因为在阅读文档时它的 player $size 是 2? 即原子性是否跨越查询和更新语句的更新部分?

编辑更深入的事件序列:

考虑同时触发两次相同的更新(U1 和 U2)。以下事件序列是否可能?

  1. U1 发现文档 #1 与更新语句的查询部分匹配。
  2. U2 发现文档 #1 与更新语句的查询部分匹配。
  3. U1 在文档 #1 中推了一个新玩家。
  4. U2 在文件 #1 中推了一个新玩家。

最终结果是文档 #1 包含的玩家比预期的多,因为 U1 和 U2 都认为文档 #1 仅包含两个玩家。

4

3 回答 3

4

我在 mongodb-user 组上问过这个问题。http://groups.google.com/group/mongodb-user/browse_thread/thread/e61e220dc0f6f64c

根据 Marc(在 10gen 工作)的回答,我描述的情况不会发生。

您描述的情况是不可能的;两个更新都没有修改同一个文档的危险。

于 2012-04-11T09:54:46.687 回答
1

更新:不知道我的知识了……见“ABA Nuance”。请不要接受这个答案(或我在下面的评论),因为它可能不正确。很想得到纠正。


您对 atomic 的解释不正确(我可以肯定,当文档更新时,没有其他更新会覆盖我之前的更改)。其他更新可以(并且将会)覆盖您的更改。但他们不会以会干扰查询完整性的方式进行操作。

重要的是要知道 MongoDB 更新在单个文档上是原子的。因此,当文档与您的查询匹配时,它会被“锁定”并准备好进行更新。请注意,您的更新 ( $push) 在被锁定的同一个文档中工作。更新完成后,锁被释放。

我不确定我是否理解“原子性是否跨越查询和更新语句的更新部分”,但是:原子意味着其他查询不能与我们的查询混淆。我们的查询可以更改本身“锁定”的数据。

免责声明:我不了解 MongoDB 用于确保这种原子性的内部机制,因此从技术角度来看(尤其是与锁定相关的)可能缺乏这种描述 - 但它在概念上是有效的。从外部角度来看,这就是它的工作原理。

于 2012-04-06T09:14:17.640 回答
0

根据您写下的事件顺序,您确实可以拥有太多的玩家。更新的“查找”和“更新”的工作方式非常类似于自己使用“查找”然后对您正在迭代的每个文档进行“更新”。您可能想看看“$atomic”运算符:http ://www.mongodb.org/display/DOCS/Atomic+Operations#AtomicOperations-ApplyingtoMultipleObjectsAtOnce

于 2012-04-06T10:46:45.700 回答