写关注(write concern)描述了从MongoDB请求的对独立运行mongod、副本集或分片的集群的写入操作的确认级别。在分片的集群中,mongos 实例将写关注(write concern)传递给分片。
注意
对于多文档事务,您可以在事务级别而非单个操作级别设置写关注。请勿为事务中的写入操作显式设置写关注。
副本集和分片的集群支持全局默认写关注(write concern)。没有显式写关注(write concern)的操作会继承全局默认。默认的全局写关注(write concern)为“大多数”。有关更多信息,请参阅 setDefaultRWConcern。
要了解有关为 MongoDB Atlas 中托管的部署设置写关注的更多信息,请参阅使用 MongoDB Atlas 构建弹性应用程序
写关注说明
写关注可包括以下字段:
{ w: <value>, j: <boolean>, wtimeout: <number> }
j: Requests acknowledgment that the write operation has been written to the on-disk journal.
wtimeout: Specifies a time limit to prevent write operations from blocking indefinitely.
w 选项
w 选项会请求确认写入操作已传播到指定数量的 mongod 实例或带有指定标记的 mongod 实例。如果写关注缺少 w 字段,MongoDB 则会将 w 选项设为默认写关注。
注意
如果使用 setDefaultRWConcern 来设置默认写关注,则须指定 w 字段值。
w 选项支持以下 w: <value>写关注(write concern):
值 | 说明 |
|---|---|
要求确认计算出的大多数有数据投票权的节点已将更改持久写入其本地 oplog。然后,节点在从本地 oplog 读取更改时异步应用这些更改。 副本集中有数据投票权的节点是主节点和 如需了解更多信息,请参阅在 { w: "majority" } 写入后读取。
示例,考虑一个具有3 个投票成员、主节点-从节点-从节点 (PSS) 的副本集。对于此副本集,计算出的多数为 2,并且写入必须传播到主节点 (primary node in the replica set)和一个从节点(secondary node from replica set)的oplog,以向客户端确认写关注(write concern)。 隐藏成员、延迟成员和 0大于 延迟的从节点在所配置的 If you specify a See Acknowledgment Behavior for when | |
要求确认写入操作已传播到指定数量的
示例,一个 3 节点副本集,具有一个主节点 (primary node in the replica set)和 2 个从节点(secondary node from replica set)。指定 隐藏成员、延迟成员和优先级 0成员可以确认 延迟的从节点在所配置的 See Acknowledgment Behavior for when | |
要求确认写入操作已传播到满足 如果自定义写关注(write concern)仅要求主节点 (primary node in the replica set)确认,并且在写入操作复制到任何从节点(secondary node from replica set)之前主节点 (primary node in the replica set)节点会降级,则可以回滚数据。 See Acknowledgment Behavior for when |
j 选项
j 选项会要求 MongoDB 确认写入操作已写入磁盘日志。
If With |
注意
将包含
j: true的写关注(write concern)给运行但未日志记录的mongod实例会产生错误。If journaling is enabled,
w: "majority"may implyj: true. ThewriteConcernMajorityJournalDefaultreplica set configuration setting determines the behavior. See Acknowledgment Behavior for details.包含或暗示
j: true的写关注会导致日志立即同步。请参阅日志记录过程。
wtimeout
此选项指定一个时间限制(以毫秒为单位),即在主节点 (primary node in the replica set)上操作成功后,写入操作传播到足够多的节点以实现写关注(write concern)。如果 w 小于或等于 1,则 wtimeout 不应用。如果写入操作在此时限内未达到写关注(write concern), MongoDB将返回写关注(write concern)错误。
wtimeout 即使所需写关注最终会成功,也会导致写入操作在达到指定限制后返回写关注错误。当这些写入操作返回时,MongoDB 不会撤消在写关注超过 wtimeout 时间限制之前已执行的成功数据修改。
如果未指定 wtimeout 选项且写关注的级别无法实现,写入操作则会无限期阻塞。将 wtimeout 值指定为 0 等同于不带 wtimeout 选项的写关注。
注意
要主节点 (primary node in the replica set)写入操作设立时间限制,请使用maxTimeMS() 方法。
隐式默认写关注
The implicit default write concern is w: majority. w: majority ensures write durability by requiring replica sets to wait for on-disk journaling by default, controlled by writeConcernMajorityJournalDefault. However, there is an edge case for replica set deployments containing arbiters:
副本集的投票多数是 1 加投票成员数量的一半,四舍五入。如果数据承载投票成员的数量不超过投票多数,则默认写关注为
{ w: 1 }。在所有其他场景中,默认写关注为
{ w: "majority" }。
具体来说,MongoDB 使用以下公式来确定默认写关注:
if [ (#arbiters > 0) AND (#non-arbiters <= majority(#voting-nodes)) ] defaultWriteConcern = { w: 1 } else defaultWriteConcern = { w: "majority" }
例如,考虑以下部署以及各自的默认写关注:
Non-Arbiters | 仲裁节点 | 投票节点 | 多数投票节点 | 隐式默认写关注 |
|---|---|---|---|---|
2 | 1 | 3 | 2 |
|
4 | 1 | 5 | 3 |
|
在第一个示例中:
有 2 个非仲裁节点和 1 个仲裁节点,共有 3 个投票节点。
多数投票节点(1 加 3 的一半,四舍五入)为 2。
非仲裁节点的数量 (2) 等于多数投票节点 (2),导致隐式写关注为
{ w: 1 }。
在第二个示例中:
共有 5 个投票节点,其中有 4 个非仲裁节点和 1 个仲裁节点。
多数投票节点(1 加 5 的一半,四舍五入)为 3。
非仲裁节点的数量 (4) 大于多数投票节点 (3),导致隐式写关注为
{ w: "majority" }。
On a sharded cluster, DDL (Data Definition Language) operations run with write concern "majority". If you specify a different write concern, the operation overrides the provided write concern with "majority".
确认行为
The w option and the j option determine when mongod instances acknowledge write operations.
独立运行的实例
独立运行的mongod 会在向内存中应用写入操作或写入磁盘上日志后确认写入操作。下表列出了具有相关写关注(write concern)的独立运行的实例的确认行为:
j 未指定 | j:true | j:false | |
|---|---|---|---|
| inMemory | On-disk journal | inMemory |
| 磁盘日志(如果与日记一起运行) | On-disk journal | inMemory |
注意
With writeConcernMajorityJournalDefault set to false, MongoDB does not wait for w: "majority" writes to be written to the on-disk journal before acknowledging the writes. As such, "majority" write operations could possibly roll back in the event of a transient loss (e.g. crash and restart) of a majority of nodes in a given replica set.
副本集
The w value determines the number of replica set members that must acknowledge the write before returning success. For each eligible member, the j option determines whether the member acknowledges writes after applying the write in memory or after writing to the on-disk journal.
w: "majority"Any data-bearing voting member of the replica set can contribute to write acknowledgment of
"majority"write operations.下表列出了该成员何时可根据 j 值来确认写入操作:
j未指定确认取决于
writeConcernMajorityJournalDefault的值:如果为
true,则确认要求MongoDB通过将写入同步到磁盘上日志来使写入持久性,相当于j: true。writeConcernMajorityJournalDefault默认为true如果为
false,则确认要求在内存中进行写入操作,相当于j: false。
j: true确认要求MongoDB通过将写入同步到磁盘上的日志记录来使写入持久性。
j: false确认要求在内存中进行写入操作。
通常,如果设立了
j: false,则无需将操作写入磁盘上日志。 但是,如果设置了writeConcernMajorityJournalDefault: true,则即使设立了j: false,也需要设立操作写入日志。如果设立了
j: false和writeConcernMajorityJournalDefault: true,则写入操作将异步写入日志。在将日志刷新到磁盘之前,设立了
w: majority的写入不会被确认为完成。w: majority无论j设置如何,写入操作都会等待"majority"读取快照完成。 这是因为,如果设立了writeConcernMajorityJournalDefault: true,则多数读取快照基于多数日志写入。写入操作向客户端应用程序返回并向
w: majority确认后,如果设立了majority读关注(read concern),则应用程序可以读取写入结果。
For behavior details, see
w: "majority"Behavior.w: <number>副本集的任一承载数据的成员均可参与 w:<number> 写入操作的写入确认。
下表列出了该成员何时可根据 j 值来确认写入操作:
j未指定确认需要在内存中执行写入操作,相当于
j: false。j: true确认要求MongoDB通过将写入同步到磁盘上的日志记录来使写入持久性。
j: false确认要求在内存中进行写入操作。
注意
Hidden, delayed, and priority 0 members can acknowledge w: <number> write operations.
延迟的从节点在所配置的 secondaryDelaySecs 之前无法返回写入确认。
在 { w: "majority" } 写入后读取
从MongoDB 8.0 开始,大多数承载数据的节点持久写入oplog条目后,{ w: "majority" } 写入会返回确认。然后,节点从本地 oplog 读取更改时会异步应用更改。在早期版本中, MongoDB会等到节点应用写入后再返回确认。
在 { w: "majority" }写入确认之后立即对从节点进行查询,可能会在从从节点(secondary node from replica set)应用写入更改之前从集合中读取数据。
如果您的应用程序从节点读取并需要立即访问{ w: "majority" }写入中的更改,请在因果一致的会话中运行这些操作。
更多信息
读关注与写关注建议
To read your own writes on the primary, use the "majority" read concern and the { w: "majority" } write concern. During an election, a read routed to the former primary can return a snapshot that does not include a majority-acknowledged write accepted by the new primary.
If you use a { w: n } write concern where n is greater than the calculated majority of the cluster's nodes and the cluster uses the default settings, enable the write concern "j" option to acknowledge the write to the journal. The "majority" read concern only allows you to read updates that are durable on a majority of nodes in the replica set.
注意
如果您执行有 { w: n } 写关注(write concern)的写入,且 n 大于计算出的多数,则在没有日志记录且使用默认集群设置的情况下,您可能会在该写入在多数节点上持久性之前收到写入确认。
因果一致的会话和写关注
因果一致的客户端会话只有在以下情况下,因果一致的客户端端会话才能保证因果一致性:
关联的读取操作使用
"majority"读关注,而the associated write operations use
"majority"write concern.
有关详细信息,请参阅因果一致性。
w: "majority" 行为
With
writeConcernMajorityJournalDefaultset tofalse, MongoDB does not wait forw: "majority"writes to be written to the on-disk journal before acknowledging the writes. As such,"majority"write operations could possibly roll back in the event of a transient loss (e.g. crash and restart) of a majority of nodes in a given replica set.Hidden, delayed, and priority 0 members with
members[n].votesgreater than0can acknowledge"majority"write operations.- 延迟的从节点在所配置的
secondaryDelaySecs之前无法返回写入确认。
从 MongoDB 5.0 开始,处于
STARTUP2状态的副本集节点不参与对写入操作的多数节点确认。
local 数据库不支持写关注
The 本地数据库不支持写关注(write concern)。MongoDB默默地忽略对本地数据库中集合操作的任何配置的写关注(write concern)。
计算写关注的 majority
提示
rs.status() 返回 writeMajorityCount 字段,其中包含计算出的多数性数量。
The majority for write concern "majority" is calculated as the smaller of the following values:
所有有投票权节点的大多数,包括仲裁节点
所有承载数据的有投票权节点的数量
警告
如果计算出的多数数等于所有数据承载投票成员的数量(例如在 3节点的“主节点-从节点-仲裁节点”部署中),写关注(write concern)"majority" 可能会超时或永远不会被确认,前提是有一个数据承载投票成员已关闭或无法访问。如果可能,请使用承载数据的有投票权成员而不是仲裁节点。
例如,考虑:
具有 3 个投票成员的副本集,即主节点-从节点-从节点 (P-S-S):
所有有投票权成员的 majority 为 2。
所有承载数据的有投票权成员的数量为 3。
2计算出的多数为2 ,是 和3 中的最小值。写入必须传播到主节点 (primary
"majority"node in the replica set)和一个从节点,以向客户端确认写关注(write concern) 。具有 3 个投票节点、主节点-从节点-仲裁节点 (PSA) 的副本集:
所有有投票权成员的 majority 为 2。
所有承载数据的投票成员的数量为 2。
计算出的多数为 2,是 2 和 2 中的最小值。由于写入只能应用于数据承载成员,因此写入必须传播到主节点 (primary node in the replica set)和从从节点(secondary node from replica set),以向客户端确认写关注(write concern)
"majority"。提示
Avoid using
"majority"write concern with P-S-A or other topologies that require all data-bearing voting members to be available to acknowledge writes. For the durability guarantees of a"majority"write concern, deploy a topology that does not require all data-bearing voting members to be available, such as P-S-S.
警告
请勿在副本集中部署多个仲裁节点。请参阅有关多个仲裁节点的问题。
要将仲裁节点添加到现有副本集:
通常,如果副本集中承载数据的成员少于或等于两个,则可能需要先为副本集设置集群范围的写关注(write concern)。
请参阅集群范围的写关注(write concern),详细了解为什么可能需要设置集群范围的写关注。
在使用具有一个仲裁节点的新副本集之前,您不需要更改集群范围的写关注(write concern)。
写关注来源
从 4.4 版本开始,MongoDB 会跟踪写关注 provenance,而后者表示特定写关注的来源。您可能会在 getLastError 指标中看到 provenance、写关注错误对象和 MongoDB 日志。
下表显示了可能的写关注 provenance 值及其重要性:
来源 | 说明 |
|---|---|
| 应用程序中指定了写关注。 |
| 写入关注源自自定义的默认值。请参阅 |
| 写关注源自副本集的 |
| 在没有所有其他写入关注规范的情况下,写入关注源自服务器。 |
写关注与提交法定人数对比
索引构建使用提交法定人数。
写入操作使用写关注。
集群中的每个承载数据的节点均为一个有投票权成员。
提交法定人数指定了必须准备多少个承载数据的有投票权节点,或是哪些有投票权节点(包括主节点)来提交同步索引构建。主节点才会执行提交。
写关注是指确认写入操作已传播到指定数量的实例的级别。
Changed in version 8.0:
提交法定人数指定了在主节点提交索引构建之前必须有多少个节点准备好完成索引构建。相反,当主节点已提交索引构建时,写关注则指定了在此命令返回成功之前有多少个节点必须复制索引构建操作日志条目。
在以前的版本中,当主节点提交索引构建时,写关注会指定在此命令返回成功之前有多少个节点必须完成索引构建。