写入关注
写入关注度描述了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>
写关注可用
值 | 描述 |
---|---|
请求确认计算出的数据承载投票成员的大多数已将更改持久地写入其本地的 多数 操作日志。然后,成员将异步地将更改应用于它们从本地操作日志中读取时。 已更改版本8.0: MongoDB 在确认写操作之前不会等待成员应用更改,这与之前的版本不同。 副本集的数据承载投票成员包括主节点和任何具有 有关更多信息,请参阅在写入{ w: "majority" }之后读取。
例如,考虑一个由3个投票成员组成的副本集,即主-辅助-辅助(P-S-S)。对于这个副本集,计算出的多数是两个,写入必须传播到主节点和一个辅助节点的操作日志中,以向客户端确认写入关注点。 具有 延迟的辅助节点最早可以在配置的 写入操作返回客户端的 如果您为多文档事务指定了 有关何时 | |
请求确认写操作已传播到指定的
大于 1 的 例如,考虑一个有主节点和 2 个副节点的 3 成员复制集。指定 隐藏、延迟和优先级 0成员可以确认 延迟的辅助节点最早可以在配置的 有关何时 | |
请求确认写操作已传播到满足在 如果自定义写关注仅要求从主节点获得确认,并且在写操作复制到任何从节点之前主节点已降级,则可以回滚数据。 有关何时 |
j
选项
j
选项请求MongoDB确认写操作已写入到磁盘日志。
如果 使用 |
注意
将包含
j: true
的写入关注指定给未开启日志记录的mongod
实例将产生错误。如果启用了日志记录,则
w: "majority"
可能意味着j: true
。副本集配置设置writeConcernMajorityJournalDefault
确定了行为。有关详细信息,请参阅 Acknowledgment Behavior。包含或意味着
j: true
的写入关注将立即同步日志。请参阅 Journaling Process。
wtimeout
此选项指定写入关注的超时时间,以毫秒为单位。只有当w
值大于1
时,wtimeout
才适用。
wtimeout
会导致写入操作在指定限制后返回错误,即使所需的写入关注最终也会成功。当这些写入操作返回时,MongoDB 不会撤销在写入关注超过wtimeout
时间限制之前执行的成功数据修改。
如果您未指定wtimeout
选项,并且写入关注级别不可达到,则写入操作将无限期阻塞。指定0
的wtimeout
值等同于没有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 }
。
在第二个例子中
共有4个非仲裁节点和1个仲裁节点,总共5个投票节点。
投票节点的多数(1加上5的一半,向下取整)为3。
非仲裁节点的数量(4)大于投票节点的多数(3),导致隐式写关注为
{ w: "majority" }
。
确认行为
选项 w 和选项 j 决定了何时 mongod
实例确认写操作。
独立模式
独立的 mongod
实例在将写操作应用在内存中或写入磁盘日志后确认写操作。以下表格列出了独立模式和相关的写关注行为
j 选项未指定 | j:true | j:false | |
---|---|---|---|
写: 1 | 内存中 | 磁盘日志中 | 内存中 |
w: "majority" | 磁盘日志(如果启用日志记录) | 磁盘日志中 | 内存中 |
注意
将 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
确认需要写入到内存。
通常,如果设置
j: false
,则不需要将操作写入磁盘日志。然而,如果设置writeConcernMajorityJournalDefault: true
,即使设置j: false
,也必须将操作写入日志。如果设置
j: false
和writeConcernMajorityJournalDefault: true
,则写入操作异步写入日志。设置
w: majority
的写入操作在日志刷新到磁盘之前不会被视为已完全确认。w: 大多数
写入操作等待完成"majority"
读取快照,无论j
设置如何。这是因为如果设置了writeConcernMajorityJournalDefault: true
,则大多数读取快照基于已记录的大多数写入。在写入操作向客户端应用程序返回
w: 大多数
确认后,如果设置了majority
读取关注点,则应用程序可以读取写入的结果。
有关行为细节,请参阅
w: "majority"
行为。w: <number>
副本集中的任何承载数据的成员都可以参与 w: <number> 写入操作的确认。
以下表格列出了根据 j 值成员可以确认写入的时间。
j
选项未指定确认需要在内存中写入操作(j: false
)。j: true
确认需要写入到磁盘日志。j: false
确认需要写入到内存。
注意
隐藏、延迟和优先级 0成员可以确认 w: <number>
写操作。
延迟的辅助节点最早可以在配置的secondaryDelaySecs
之后返回写入确认。
在 { w: "majority" } 写入之后读取
从 MongoDB 8.0 开始,{ w: "majority" }
写入操作在大多数承载数据的成员持久化写入 oplog 条目后返回确认。然后,成员异步地应用它们从本地 oplog 读取的更改。在早期版本中,MongoDB 等待成员应用写入后返回确认。
在 { w: "majority" }
写入操作返回确认后立即对次级进行查询可能从次级在应用写入更改之前读取的集合中读取。
如果您的应用程序从次级读取并需要立即访问在 { w: "majority" }
写入中做出的更改,请在 因果一致性 会话中运行这些操作。
更多信息
因果一致性会话和写入关注度
在因果一致性客户端会话中,只有当
相关的读取操作使用
"majority"
读取关注度,并且相关的写入操作使用
"majority"
写入关注度时,客户端会话才保证因果一致性。
详细信息请参阅因果一致性。
w: "majority"
行为
将
writeConcernMajorityJournalDefault
设置为false
,MongoDB 在确认写入之前不会等待将w: "majority"
写入到磁盘日志。因此,在给定副本集的多数节点发生瞬时丢失(例如,崩溃和重启)的情况下,可能会回滚"majority"
写操作。具有
members[n].votes
大于0
的隐藏、延迟和优先级0成员可以确认"majority"
写入操作。延迟的辅助节点最早可以在配置的
secondaryDelaySecs
之后返回写入确认。
从MongoDB 5.0开始,处于
STARTUP2
状态的副本集成员不参与写入多数。
在本地数据库上不支持写关注local
数据库
本地数据库local database不支持写关注。MongoDB会静默忽略本地数据库集合操作上配置的任何写关注。
计算写关注的多数
提示
rs.status()
返回包含计算出的多数数字的字段writeMajorityCount
。
写关注多数"majority"
的计算为以下值中的较小值
所有投票成员(包括仲裁员)的多数 vs.
所有
data-bearing
投票成员的数量。
警告
在计算出的多数数字等于所有data-bearing
投票成员的数量(例如,在3成员主-次-仲裁员部署中)的情况下,如果数据投票成员出现故障或不可达,写关注多数"majority"
可能会超时或不会被确认。如果可能,请使用数据投票成员而不是仲裁员。
例如,考虑以下情况
一个有3个投票成员的副本集,主-次-次(P-S-S)
所有投票成员的多数是2。
所有数据投票成员的数量是3。
计算出的多数是2,2和3中的最小值。写操作必须传播到主节点和至少一个次节点以向客户端确认写关注"majority"
。一个有3个投票成员的副本集,主-次-仲裁员(P-S-A)
所有投票成员的多数是2。
所有数据投票成员的数量是2。
计算出的多数值为2,即2和2中的最小值。由于写入只能应用于承载数据的成员,因此写入必须传播到主节点和副节点以确认写入关注"majority"
到客户端。提示
避免在(P-S-A)或其他需要所有承载数据投票成员都可用以确认写入的拓扑中使用
"majority"
写入关注。希望使用"majority"
写入关注以获得持久性保证的客户应部署不需要所有承载数据投票成员都可用的拓扑(例如P-S-S)。
警告
避免在一个副本集中部署多个仲裁者。参见多个仲裁者的注意事项。
要将仲裁者添加到现有的副本集
在启动带有仲裁者的新副本集之前,您不需要更改集群范围的写入关注。
写入关注来源
MongoDB跟踪写入关注的来源
,指示特定写入关注的来源。您可能在getLastError
指标、写入关注错误对象和MongoDB日志中看到来源
。
以下表格显示了可能的写入关注来源
值及其含义
来源 | 描述 |
---|---|
clientSupplied | 写入关注是在应用程序中指定的。 |
customDefault | 写入关注是从自定义定义的默认值中起源的。参见 setDefaultRWConcern 。 |
getLastErrorDefaults | 写入关注是从副本集的
|
implicitDefault | 在没有其他写入关注规范的情况下,写入关注是从服务器中起源的。 |
写入关注与提交法定人数对比
提交法定人数和写入关注之间有重要的区别:
索引构建使用提交法定人数。
写入操作使用写入关注。
集群中每个承载数据的节点都是一个投票成员。
提交法定人数指定在主节点执行提交之前,需要多少个承载数据的投票成员,或者哪些投票成员(包括主节点)必须准备好提交一个同时索引构建。
写入关注是指写入已经传播到指定数量的实例的确认级别。
已更改版本8.0: 提交法定人数指定在主节点提交索引构建之前,需要多少个节点准备好完成索引构建。相比之下,当主节点提交索引构建时,写入关注指定在命令返回成功之前,需要多少个节点复制索引构建的操作日志条目。
在之前的版本中,当主节点提交索引构建时,写入关注指定在命令返回成功之前,需要多少个节点完成索引构建。