Docs 主页 → 开发应用程序 → MongoDB Manual
写关注
写关注说明了 MongoDB 为针对独立运行的 mongod
、副本集或分片集群的写入操作所请求的确认级别。在分片集群中,mongos
实例会将写关注传递给分片。
注意
对于多文档事务,您可以在事务级别而非单个操作级别设置写关注。请勿为事务中的写入操作显示设置写关注。
如果您为"majority"
多文档事务 指定 写关注,并且该事务无法复制到 计算出的多数 副本集 成员,则该事务可能不会立即回滚副本集成员。副本集 最终将保持一致 。事务始终会在所有副本集节点上应用或回滚。
副本集和分片集群支持设置全局默认写关注。未指定显式写关注的操作会继承全局默认写关注设置。有关更多信息,请参阅setDefaultRWConcern
。
要了解有关为 MongoDB Atlas 中托管的部署设置写关注的更多信息,请参阅使用 MongoDB Atlas 构建弹性应用程序
写关注说明
写关注可包括以下字段:
{ w: <value>, j: <boolean>, wtimeout: <number> }
w
选项
w
选项会请求确认写入操作已传播到指定数量的 mongod
实例或带有指定标记的 mongod
实例。如果写关注缺少 w
字段,MongoDB 则会将 w
选项设为默认写关注。
注意
如果使用 setDefaultRWConcern
来设置默认写关注,则须指定 w
字段值。
通过使用 w
选项,可使用以下 w: <value>
写关注:
值 | 说明 |
---|---|
要求确认写入操作已持久提交给计算出的多数承载数据的有投票权成员(即 例如,考虑一个具有3个投票成员、主节点-从节点-从节点 (PSS) 的副本集。对于此副本集,计算出的多数为 2,并且写入必须传播到主节点和一个从节点,以向客户端确认写关注。 注意0 延迟的从节点在所配置的 写入操作向客户端返回 如果您为
| |
要求确认写入操作已传播到指定数量的
例如,有一 3 成员副本集,其中包含 1 个主节点和 2 个从节点。指定 注意隐藏、延迟和优先级0成员可以确认 延迟的从节点在所配置的
| |
要求确认写入操作已传播到满足 如果自定义写关注仅要求主节点进行确认,且在将写入操作复制到任一从节点之前主节点便已退出,则可回滚数据。
|
提示
j
选项
j
选项会要求 MongoDB 确认写入操作已写入磁盘日志。
注意
将包含
j: true
的写关注指定给正在运行但未记录日志的mongod
实例会产生错误。如果已启用日志功能,则
w: "majority"
可能j: true
。writeConcernMajorityJournalDefault
副本集配置设置决定了此行为。有关详细信息,请参阅确认行为。包含或暗示
j: true
的写关注会导致日志立即同步。请参阅日志记录过程。
wtimeout
此选项指定写关注的时间限制(以毫秒为单位)。wtimeout
只适用于w
值大于 1
的情况。
wtimeout
即使所需写关注最终会成功,也会导致写入操作在达到指定限制后返回一个错误。当这些写入操作返回时,MongoDB不会撤消在写关注超过 wtimeout
时间限制之前已执行的成功数据修改。
如果未指定 wtimeout
选项且写关注的级别无法实现,写入操作则会无限期阻塞。将 wtimeout
值指定为 0
等同于不带 wtimeout
选项的写关注。
隐式默认写关注
从 MongoDB 5开始。 0 ,隐式默认写关注为w: majority
。但是,对于包含仲裁节点的部署,需要特别考虑:
副本集的投票多数是 1 加投票成员数量的一半,四舍五入。如果数据承载投票成员的数量不超过投票多数,则默认写关注为
{ w: 1 }
。在所有其他场景中,默认写关注为
{ w: "majority" }
。
具体来说,MongoDB 使用以下公式来确定默认写关注:
if [ (#arbiters > 0) AND (#non-arbiters <= majority(#voting-nodes)) ] defaultWriteConcern = { w: 1 } else defaultWriteConcern = { w: "majority" }
例如,考虑以下部署以及各自的默认写关注:
非仲裁节点 | 仲裁节点 | 投票节点 | 多数投票节点 | 隐式默认写关注 |
---|---|---|---|---|
2 | 1 | 3 | 2 | { w: 1 } |
4 | 1 | 5 | 3 | { w: "majority" } |
在第一个示例中:
有 2 个非仲裁节点和 1 个仲裁节点,共有 3 个投票节点。
多数投票节点(1 加 3 的一半,四舍五入)为 2。
非仲裁节点的数量 (2) 等于多数投票节点 (2),导致隐式写关注为
{ w: 1 }
。
在第二个示例中:
共有 5 个投票节点,其中有 4 个非仲裁节点和 1 个仲裁节点。
多数投票节点(1 加 5 的一半,四舍五入)为 3。
非仲裁节点的数量 (4) 大于多数投票节点 (3),导致隐式写关注为
{ w: "majority" }
。
确认行为
独立运行的实例
独立 mongod
在向内存中应用写入操作后或在写入磁盘上日志后,会确认该写入操作。下表列出独立实例的确认行为以及相关的写关注:
j 未指定 | j:true | j:false | |
---|---|---|---|
w: 1 | inMemory | 磁盘上日志 | inMemory |
w: "majority" | 磁盘日志(如果与日记一起运行) | 磁盘上日志 | inMemory |
注意
将writeConcernMajorityJournalDefault
设置为false
时,MongoDB 在确认写入之前不会等待w: "majority"
写入写入磁盘上日志。因此,如果给定副本集中的大多数节点短暂丢失(例如崩溃和重启), "majority"
写入操作可能会回滚。
副本集
指定给 w 的值决定了在返回成功之前必须确认写入的副本集成员数。对于每个有资格的副本集成员,j 选项决定了该成员引在向内存应用写入操作之后还是写入磁盘上日志之后确认写入操作。
w: "majority"
副本集的任何承载数据的有投票权成员都可以参与
"majority"
写入操作的写入确认。下表列出了该成员何时可根据 j 值来确认写入操作:
j
未指定确认取决于
writeConcernMajorityJournalDefault
的值:如果为
true
,则确认时要求对磁盘上日志 (j: true
) 进行写入操作。writeConcernMajorityJournalDefault
默认为true
如果为
false
,则确认需要在内存中进行写入操作(j: false
)。
j: true
确认时要求对磁盘上日志进行写入操作。j: false
确认要求在内存中进行写入操作。注意
有关行为的详细信息,请参阅
w: "majority"
行为。w: <number>
副本集的任一承载数据的成员均可参与 w: <数量> 写入操作的写入确认。
下表列出了该成员何时可根据 j 值来确认写入操作:
j
未指定确认要求在内存中进行写入操作 (j: false
)。j: true
确认时要求对磁盘上日志进行写入操作。j: false
确认要求在内存中进行写入操作。
注意
隐藏、延迟和优先级0成员可以确认w: <number>
写入操作。
延迟的从节点在所配置的 secondaryDelaySecs
之前无法返回写入确认。
更多信息
因果一致的会话和写关注
使用因果一致的客户端会话时,只有在以下情况下,客户端会话才能保证因果一致性:
关联的读取操作使用
"majority"
读关注,而关联的写入操作使用
"majority"
写关注。
有关详细信息,请参阅因果一致性。
w: "majority"
行为
将
writeConcernMajorityJournalDefault
设置为false
时,MongoDB 在确认写入之前不会等待w: "majority"
写入写入磁盘上日志。因此,如果给定副本集中的大多数节点短暂丢失(例如崩溃和重启),"majority"
写入操作可能会回滚。0
members[n].votes
大于0
的 隐藏 、"majority"
延迟 和 优先级 成员可以确认 写入操作。延迟的从节点在所配置的
secondaryDelaySecs
之前无法返回写入确认。
从 MongoDB 5.0 开始,处于
STARTUP2
状态的副本集节点不参与对写入操作的多数节点确认。
local
数据库不支持写关注
本地数据库不支持写关注。MongoDB 会静默忽略为针对本地数据库中集合的操作所配置的全部写关注。
计算写关注的 majority
提示
rs.status()
返回包含计算出的多数数的writeMajorityCount
字段。
写关注"majority"
的多数按以下值中较小的值计算:
所有有投票权成员(包括仲裁节点)的 majority 与
所有承载数据的有投票权成员的数量。
警告
如果计算出的多数数等于所有承载数据的有投票权成员的数量(例如使用3成员主节点-从节点-仲裁节点部署),则在以下情况下,写关注"majority"
可能会超时或永远不会得到确认:承载数据的有投票权成员已关闭或无法访问。如果可能,请使用承载数据的有投票权成员而不是仲裁节点。
例如,考虑:
具有 3 个投票成员的副本集,即主节点-从节点-从节点 (P-S-S):
所有有投票权成员的 majority 为 2。
所有承载数据的有投票权成员的数量为 3。
计算出的多数为2 ,即2和3中的最小值。写入必须传播到主节点和一个从节点,以向客户端确认写关注"majority"
。具有 3 个有投票权成员(即,主节点-从节点-仲裁节点 (P-S-A))的副本集
所有有投票权成员的 majority 为 2。
所有承载数据的投票成员的数量为 2。
计算出的多数为2 ,即2和2中的最小值。由于写入只能应用于数据承载成员,因此写入必须传播到主节点和从节点,以向客户端确认写关注"majority"
。提示
避免将
"majority"
写关注与 (PSA) 或其他要求所有数据承载投票成员都可用于确认写入的拓扑一起使用。希望使用"majority"
写关注获得持久性保证的客户应改为部署不要求所有数据承载投票成员都可用的拓扑(例如 PSS)。
警告
请勿在副本集中部署多个仲裁节点。请参阅有关多个仲裁节点的问题。
要将仲裁节点添加到现有副本集:
通常,如果副本集中承载数据的成员少于或等于两个,则可能需要先为副本集设置集群范围的写关注(write concern)。
请参阅集群范围的写关注(write concern),详细了解为什么可能需要设置集群范围的写关注。
在使用具有一个仲裁节点的新副本集之前,您不需要更改集群范围的写关注(write concern)。
提示
另请参阅:
写关注来源
MongoDB 跟踪写关注provenance
,它指示特定写关注的来源。您可能会看到 { getLastError
指标、写关注错误对象和 MongoDB 日志中显示provenance
。
下表显示了可能的写关注 provenance
值及其重要性:
来源 | 说明 |
---|---|
clientSupplied | 应用程序中指定了写关注。 |
customDefault | 写入关注源自自定义的默认值。请参阅 setDefaultRWConcern 。 |
getLastErrorDefaults | 写关注源自副本集的 settings.getLastErrorDefaults 字段。 |
implicitDefault | 在没有所有其他写入关注规范的情况下,写入关注源自服务器。 |
写关注与提交法定人数对比
索引构建使用提交法定人数。
写入操作使用写关注。
集群中的每个承载数据的节点均为一个有投票权成员。
提交法定人数指定了必须准备多少个承载数据的有投票权成员或是哪些有投票权成员(包括主节点)来提交同步索引构建。主节点才会执行提交。
写关注是指确认写入操作已传播到指定数量的实例的级别。
提交法定人数指定了在主节点提交索引构建之前必须有多少个节点准备好完成索引构建。相反,当主节点已提交索引构建时,写关注则指定了在此命令返回之前有多少个节点必须完成索引构建。