【问题标题】:Transactional behavior with mongoose与猫鼬的交易行为
【发布时间】:2014-06-24 20:08:30
【问题描述】:

假设我在猫鼬中有一个架构A。它看起来像这样:

{
    arr: [{
        num: Number,
        text: String
    }]
}

现在我要执行以下操作:

  1. 选择一个A,即a

  2. 获取a.arr的项目的实际数量。

  3. a.arr 添加一个新元素,其中包含计数和文本。

我的实现:

A.findOne({_id: someId}, function(err, a) {
    var count = a.arr.length;
    a.push({
        count: count,
        text: 'some text'
    });
    a.save(...)
});

到目前为止工作正常。 但我的问题: 如果我执行该并发,假设有 5 个进程,一些进程在其他进程保存之前执行 findOne。 所以前几个的 count 是 0,然后当他们保存后,它会立即变为 3 或 4 用于下一个进程。

但我希望它能够串行执行。

如何实现?

谢谢!

【问题讨论】:

    标签: arrays node.js mongodb concurrency mongoose


    【解决方案1】:

    mongo 中不支持事务,但您可以按照http://cookbook.mongodb.org/patterns/perform-two-phase-commits/ 中的描述实现两阶段提交

    或者,您可以在进程之间实现一些协调,如果数据支持这种情况,则将数据范围分配给特定的进程。

    编辑: 以非常简单的形式,您可以通过添加属性 lockProcessId 并使用以下命令序列来实现一些乐观的文档锁定:

    db.A.findAndModify({_id: someId, lockProcessId:{$exists:false}},{$set:{lockProcessId: someProcessId},{new:true}}
    
    db.A.findAndModify({_id: someId, lockProcessId:someProcessId},{$push:{arr:{ count: count,text:'some text'}},$unset:{lockProcessId:1}})
    

    如果第一个查询没有返回任何内容,进程应该跳过这个文档,否则它应该运行第二个查询

    但是,如果某些进程在中间死掉,您可能会锁定一些文档,可能您需要一些调度程序来清除锁定状态。

    【讨论】:

    • 谢谢!嗯,在两阶段提交的情况下,您事先知道并发方的数量。但我有一个案例,这些进程是由进来的请求生成的,可以是任意数字。我认为需要流程协调。
    猜你喜欢
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 2019-02-09
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多