【问题标题】:MongoDB Integrity Update edge caseMongoDB Integrity Update 边缘案例
【发布时间】:2016-03-30 07:53:06
【问题描述】:

您好,我在数据库中有以下 JSON,

{
   recordName : String
   amount : Number
   approved : Boolean
}

假设我有两个用户同时发出这两个命令

Record.update({recordName: "test", approved: false},{$set: {amount : 5000, approved: false,...)

Record.update({recordName: "test", approved: false},{$set: {amount : 9999, approved: true,...)

是否始终保证最终结果始终为金额 9999 并且批准为真?

我担心最终结果有时可能是金额 5000 并且批准是错误的。

我不太确定 MongoDB 管道。

我相信更新分为两个阶段? Find {recordName: "test", approved: false} 然后更新?如果两个查询都已经找到了该条目怎么办,那么这一切都取决于谁先更新?

【问题讨论】:

  • 单文档操作总是atomic,但不保证执行顺序。在您的情况下,如果其中一个查询都将approved 状态更新为“true”,则其中一个查询将无法更新。
  • 或者你可以利用文档版本控制技术,看看这个question
  • @BatScream 我读过有关原子和并发的文章。似乎mongodb会在写入或更新时锁定进程。所以问题是。更新过程是指仅当文档更新时,还是指查询数据再更新的全过程?

标签: mongodb


【解决方案1】:

因为单个文档更新是atomic,所以无论你的两个命令执行的顺序如何,文档最终都会变成:

{amount : 9999, approved: true, ...}

如果第一个命令先执行,那么第二个命令将覆盖它。

如果第二个命令先执行,那么第一个命令无效,因为approve 现在是true,所以更新条件不匹配。

您正在(正确地)做的是行之有效的optimistic concurrency"update if current" 方法来管理并发访问。

【讨论】:

  • 嗨。谢谢你的回答!但还有一些事情与我有关。我相信“原子”更新仅指更新操作本身。想象一下表格未获批准。管理员按下批准和工人按下编辑大致相同的时间。然后管理员通过了approve = false的查询。 Worker 也通过了approve = false 的查询。现在取决于谁首先获得实际更新?如果模式是这样的 Q1,U1,Q2,U2 或 Q2,U2,Q1,U1 ,则上述更新操作有效,其中 Q 是查询,U 是更新。但是,如果 Q1、Q2、U1、U2,它将不起作用。我希望我说得通。
  • 不,先生,更新的原子性质适用于条件检查和文档修改,作为一个原子单元。
  • 之所以我认为查询和更新是分开发生的,是因为 mongoDB 的这条语句“如果所有 update() 操作在任何客户端成功插入数据之前完成查询部分,并且没有唯一索引name 字段,那么每个更新操作都可能导致插入。” docs.mongodb.org/v3.0/reference/method/db.collection.update 。如果这真的是原子的,那么每个结果都不可能导致插入?
  • 这仅适用于插入文档的{upsert: true} 更新,而不是原子地修改现有文档。
  • 非常感谢您的澄清!我花了 6 个小时研究认为查询和更新是分开的!
猜你喜欢
  • 2010-10-28
  • 1970-01-01
  • 2012-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-18
  • 2018-04-15
  • 2019-07-29
相关资源
最近更新 更多