【问题标题】:Why do my MongoDB simultaneous $push updates fail?为什么我的 MongoDB 同时 $push 更新失败?
【发布时间】:2013-09-01 05:30:39
【问题描述】:

我正在对表单进行一些更新

update(
  { "uuid": someUuid, "revision.versionNumber": someVersionNumber},
  { "$set": { "meta.someId": someId }, "$push": { "meta.someMessages": someMessage } }
)

有时我会看到当调用相同的 uuidversionNumbersomeId 并使用不同的 someMessage 时,第一次更新会成功,但第二次会默默失败。

我在 mongo 日志中看到以下内容,因此我知道更新正在进入数据库, 请注意,第一个更新与第三个具有相同的查询,但第一个具有 nupdated: 1 而第三个具有 nupdated: 0

Wed Aug 28 14:50:24 [conn18] update some-db.some_collection query: { uuid: "b841f303-a054-4eb9-8885-9d3ebf9906a1", revision.versionNumber: 9 } update: { $set: { meta.someId: "521e6fe4036420f90371a922" }, $push: { meta.someMessages: { event: "instance.complete", timestamp: new Date(1377726624985) } } } nscanned:2507 nmoved:1 nupdated:1 keyUpdates:0 numYields: 19 locks(micros) w:6010 9ms
Wed Aug 28 14:50:24 [conn18] run command some-db.$cmd { getlasterror: 1, fsync: true }
Wed Aug 28 14:50:24 [conn14] update some-db.some_collection query: { uuid: "843f424d-8a62-4a8b-853f-dc2e9c42b309", revision.versionNumber: { $lt: 10 }, meta.deleted: true } update: { $set: { meta.deleted: false } } nscanned:3243 nupdated:0 keyUpdates:0 numYields: 23 locks(micros) w:8431 11ms
Wed Aug 28 14:50:24 [conn14] run command some-db.$cmd { getlasterror: 1, fsync: true }
Wed Aug 28 14:50:24 [conn5] update some-db.some_collection query: { uuid: "b841f303-a054-4eb9-8885-9d3ebf9906a1", revision.versionNumber: 9 } update: { $set: { meta.someId: "521e6fe4036420f90371a922" }, $push: { meta.someMessages: { event: "instance.complete.success", timestamp: new Date(1377726624985) } } } nscanned:3242 nupdated:0 keyUpdates:0 numYields: 20 locks(micros) w:5684 9ms

这里也是 mongosniff 的输出

update  flags:0 q:{ uuid: "85700d8c-8946-4b09-968b-968f76d31028", revision.versionNumber: 13 } o:{ $set: { meta.someId: "521e7b12036420f90371b515" }, $push: { meta.someMessages: { event: "instance.complete", timestamp: new Date(1377729439093) } } }
319 some-db.some_collection

    update  flags:0 q:{ uuid: "a460019d-443b-4b59-b23e-1eae19e26c31", revision.versionNumber: 14 } o:{ $set: { meta.someId: "521e7b2f036420f90371b579" }, $push: { meta.someMessages: { event: "task.start", timestamp: new Date(1377729439093) } } }
123 some-db.some_collection

    query: { uuid: "a2558f5c-d825-4ec4-bbc4-7e48b1cb3c60", isLatest: true }  ntoreturn: -1 ntoskip: 0
302 some-db.some_collection

    update  flags:0 q:{ uuid: "85700d8c-8946-4b09-968b-968f76d31028", revision.versionNumber: 13 } o:{ $set: { meta.someId: "521e7b12036420f90371b515" }, $push: { meta.someMessages: { event: "instance.complete.success", timestamp: new Date(1377729439093) } } }
173 some-db.some_collection

【问题讨论】:

  • 字段 uuid 上是否有索引?
  • @AsyaKamsky 没有。这会有所不同吗?为什么?
  • 我认为它会 - 请注意“获取”的更新首先会增加文档,导致它被移动到磁盘“nmoved:1”上,这意味着这取决于其他更新的扫描方式集合有可能它“错过”了文档(两个进程都会定期产生,这意味着世界的状态可能会改变:numYields:20)该索引还有助于降低更新速度 - 您正在扫描超过 2500 个文档以找到 1要更新,使用索引时,nscanned 会低得多,并且两次更新都将保证以相同的顺序“遍历”索引。
  • 不能扫描_id吗?一个举动不应该影响它。解释()的结果是什么?你在用什么驱动,你在做异步调用吗?
  • 这是在特定情况下的数据竞争情况,但是是的,这正是我要说的。

标签: mongodb scala playframework-2.1 casbah salat


【解决方案1】:

作为此错误的解决方法,我建议使用 findAndModify 并检查结果以确保您的更新发生。

    dbCollection.findAndModify(
{ "uuid": someUuid, "revision.versionNumber": someVersionNumber},
[], { "$set": { "meta.someId": someId }, "$push": { "meta.someMessages": someMessage } }, {safe: true, 'new' : true}, function(err, updated){
     if(err){
     //handle the error
    }
    if(updated.meta.someMessages doesn't contain your message) {
     //try it again or report it to the client
    }     
    });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-29
    • 2011-03-09
    • 2014-01-01
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多