【问题标题】:MongoDB: Are bulk operations written to the oplog as a whole?MongoDB:批量操作是否作为一个整体写入 oplog?
【发布时间】:2015-08-22 13:30:07
【问题描述】:

当我在 MongoDB 3 中发出一个有序的批量操作时,是否将批量操作作为一个整体写入 oplog,以便在服务器崩溃后作为一个整体进行重播?

这个问题的基本原理如下:

我知道没有真正的事务,但我可以使用$isolated 关键字来获得一些读取一致性(在某些情况下)。 除了是否是良好的模式设计之外,让我们假设我必须一次更新可能不同集合中的多个文档,这将是 SQL 中的一个事务。我不关心数据在任何时候都处于不一致的状态,但是我确实要求数据最终是一致的。因此,虽然我可能不关心操作期间的错误和丢失的回滚,但我需要在某个时间点完全执行更新序列根本不执行为了让它们在批量操作过程中遇到意外的服务器故障或关闭(例如,因为随机的 CoreOS 更新)。

【问题讨论】:

    标签: mongodb mongodb-query


    【解决方案1】:

    我将带着一个一般性的警告进入这一点,我承认我什至没有看过结果,但基本原则似乎从一开始就对我有效。

    您需要在这里考虑的是在一般调用中呈现的“漂亮的语法糖”的“幕后实际发生的事情”。这意味着基本上是查看您调用的操作的“命令形式”实际执行的操作。在这种情况下"update"

    因此,如果您已经查看过该链接,请考虑以下 "Bulk" 更新表单:

    var bulk = db.collection.initializeOrdedBulkOp();
    
    bulk.find({ "_id": 1 }).updateOne({ "$set": { "a": 1 } });
    bulk.find({ "_id": 2 }).updateOne({ "$set": { "b": 2 } });
    
    bulk.execute();
    

    现在您已经知道这是作为 一个 请求发送到服务器的,但您可能没有考虑的是“幕后”发出的实际“请求”实际上是这样的:

    db.runCommand({
        "update": "collection",
        "updates": [
            { "q": { "_id": 1 }, "u": { "$set": { "a": 1 } } },
            { "q": { "_id": 2 }, "u": { "$set": { "b": 2 } } }
        ],
        "ordered": true
    })
    

    因此,您在“更新”操作下的日志中实际看到的内容实际上类似于(从完整输出缩写为仅查询):

    { "q": { "_id": 1 }, "u": { "$set": { "a": 1 } } }
    { "q": { "_id": 2 }, "u": { "$set": { "b": 2 } } }
    

    因此,这意味着带有关联命令的每个操作都在 oplog 中,用于“重播”复制和/或您可能执行的其他操作,例如专门“重播”oplog 条目。

    我可以确定这是实际发生的事情,甚至不用看,因为我知道驱动程序如何实现实际调用,并且每个调用都以这种方式保存在 oplog 中是有道理的。

    因此“作为一个整体”,那么没有。这些不是“事务”,即使它们的提交和返回在单个请求中,它们也始终是不同的操作。但它们不是单一的操作,因此不会也不应该这样记录。

    【讨论】:

    • 不确定我是否正确,但您的结论似乎与您上面所说的相矛盾;再说一次,也许我只是愚蠢地问。所以,不同的方法:是否在第一个工作开始之前将单个更新写入 oplog,或者系统是否处于并非所有单个更新都“注册”的状态,因此从技术上讲,它们中的任何数量都可能丢失?
    • @sunside 我认为这很清楚。作为带有一个响应的“一个请求”发送,但作为“单独的操作”“提交”。所以每个更新实际上应该是一个单独的 oplog 条目,而不是一个“批处理”操作。 “技术上”我还说“不是事务”,所以没有“保证”(如果您没有得到确认响应并且服务器在此期间崩溃)批处理中提交的所有请求无论如何都是“全部”提交的。这就是 MongoDB 的基本工作方式。
    • 这个我得到了(我认为),我只是想知道内部行为是否基本上是take first, register first, perform first, take next, register, perform, ... 或更多类似于register all, perform first, perform next, ...。似乎您同时更新了您的评论。除了两阶段提交之外,您是否知道任何微不足道的解决方案?
    • @sunside 我基本上想说的是,它不是那样的。将“无序”操作视为批处理请求。这基本上意味着批处理中的所有操作都以“任何顺序”应用,因此意味着“单独的”操作和不​​同的“线程”(内部来说)。在这两种情况下,还需要考虑“错误”响应,其中只有“应用”那些成功的操作而不是那些出错的操作才有意义。 “重放”不能导致修改或插入的东西没有意义吗?
    • @sunside 嗯,这是解决“那个”问题的基本程序。 IE。标记“进行中”,做一些事情,回来并标记“完成”。这里没有“交易”。只有我们熊。
    猜你喜欢
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 2021-05-07
    • 2015-10-21
    • 2020-08-03
    相关资源
    最近更新 更多