我们有一个单独的客户端,可以连续写入两个文档({w:1}
)。
例如,原始文档可能是:
{_id: "a", value: 0}
,
{_id: "b", value: 0}
,客户端将文档“a”更新为{_id: "a", value: 1}
,然后在更新完成后,客户端将文档“b”更新为{_id: "b", value: 1}
。
第二个客户后来调用find({})
。第二个客户端从辅助服务器读取,该辅助服务器可能尚未收到所有更改。
显然它可以读取以下状态:
{_id:"a",value:0}
,{_id:"b",value:0}
{_id:"a",value:1}
,{_id:"b",value:0}
{_id:"a",value:1}
,{_id:"b",value:1}
这是主要的“真实”状态(在过去的某个时刻)。
第二个客户端可以看到如下状态:{_id:"a",value:0}
,{_id:"b",value:1}
吗?请注意,此状态从不存在于主数据库中。
P.S。 解释here说:
Secondaries ...按照它们在oplog中出现的顺序应用写操作。
这是否意味着辅助人员按照他们在主要文件上更新的相同顺序更改文档?
P.S。 find
游标是否“冻结”他们正在阅读的文档的状态(即忽略创建游标后所做的更改)?如果我使用find(...).sort({_id:-1})
或文件“a”的id是“c”(即大于“b”),情况会有所不同吗?
由于
答案 0 :(得分:1)
第一个问题:是的,次要的操作按照与主要操作相同的顺序执行。所有操作都记录在oplog中。 oplog本身不是所执行查询的日志(即updateMany()),但必须对实际文档执行什么操作,以使其操作变为幂等。
关于游标操作。在迭代光标时可能会发生文档被移动或更新。如果在更新期间索引或存储位置发生变化,则可能会发生同一文档在光标上出现两次。
有一种特殊的snapshot模式提供某种隔离,但它有一些限制,即它不能与分片一起使用
答案 1 :(得分:0)
如果我们的documnet是按照主要的顺序更新的
然后辅助文件将以相同的顺序更新文档:
可以在不应用其他更改的情况下阅读documnet
可以在不应用其他更改的情况下阅读documnet
对于锁定see this,因为mongo可以优化操作序列,即使激活文档更新也可以允许读取。