MongoDB:批量操作是否作为一个整体写入oplog?

sun*_*ide 4 mongodb mongodb-query

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

这个问题的理由如下:

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

Bla*_*ven 6

我将在进入这个话题时附带一个一般性的警告,我承认我什至没有看过结果,但基本原则从一开始对我来说似乎是有效的。

这里您需要考虑的是在一般调用中提供的“良好语法糖”的“幕后实际发生的情况”。这基本上意味着查看您所调用的操作的“命令形式”实际执行的操作。在这种情况下“更新”

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

var bulk = db.collection.initializeOrdedBulkOp();

bulk.find({ "_id": 1 }).updateOne({ "$set": { "a": 1 } });
bulk.find({ "_id": 2 }).updateOne({ "$set": { "b": 2 } });

bulk.execute();
Run Code Online (Sandbox Code Playgroud)

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

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

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

{ "q": { "_id": 1 }, "u": { "$set": { "a": 1 } } }
{ "q": { "_id": 2 }, "u": { "$set": { "b": 2 } } }
Run Code Online (Sandbox Code Playgroud)

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

我什至不用看就确信这就是实际发生的情况,因为我知道驱动程序如何实现实际调用,并且每个调用以这种方式保存在 oplog 中是有意义的。

因此“作为一个整体”,则不是。这些不是“交易”,并且始终是不同的操作,即使它们的提交和返回是在单个请求内。但它们不是单一操作,因此不会也不应该如此记录。