Docs 菜单
Docs 主页
/
MongoDB Manual
/

写关注

在此页面上

  • 写关注说明
  • 隐式默认写关注
  • 确认行为
  • 更多信息

写关注描述了从MongoDB请求的对独立运行 mongod副本集分片的集群的写入操作的确认级别。 在分分片的集群中, mongos实例会将写关注(write concern)传递给分片。

注意

对于多文档事务,您可以在事务级别而非单个操作级别设置写关注。请勿为事务中的写入操作显示设置写关注。

如果您为多文档事务指定 "majority" 写关注,并且该事务无法复制到计算出的大多数副本集成员,则该事务可能不会立即在副本集成员上回滚。副本集最终将保持一致。事务始终在所有副本集成员上应用或回滚。

副本集和分片集群支持设置全局默认的写关注。未指定显式写关注的操作会继承全局默认写关注设置。有关详细信息,请参阅 setDefaultRWConcern

要了解有关为 MongoDB Atlas 中托管的部署设置写关注的更多信息,请参阅使用 MongoDB Atlas 构建弹性应用程序

写关注可包括以下字段:

{ w: <value>, j: <boolean>, wtimeout: <number> }
  • w 选项会请求确认写入操作已传播到指定数量的 mongod 实例或带有指定标签的 mongod 实例。

  • j 选项以请求确认写入操作已写入磁盘上日志,以及

  • wtimeout 选项用于指定时间限制,以防止写入操作无限期阻塞。

w 选项会请求确认写入操作已传播到指定数量的 mongod 实例或带有指定标记的 mongod 实例。如果写关注缺少 w 字段,MongoDB 则会将 w 选项设为默认写关注。

注意

如果使用 setDefaultRWConcern 来设置默认写关注,则须指定 w 字段值。

通过使用 w 选项,可使用以下 w: <value> 写关注:

说明
"majority"

要求确认计算出的大多数有数据投票权的节点已将更改持久写入其本地 oplog。然后,节点在从本地 oplog 读取更改时异步应用这些更改。

在版本 8.0 中进行了更改:MongoDB 不会像以前的版本那样,在确认写入之前等待成员应用更改。

副本集中有数据投票权的节点是主节点 members[n].votes 大于 0 的从节点。

如需了解更多信息,请参阅在 { w: "majority" } 写入后读取。

{ w: "majority" }大多数 MongoDB 部署的默认写关注。请参阅 隐式默认写关注。

例如,考虑一个具有 3 个投票权节点的副本集,即主节点-从节点-从节点 (P-S-S)。对于此副本集,计算出的 majority 为 2,并且写入必须传播到主节点和从节点的 oplog,以便向客户端确认写关注。

members[n].votes 大于 0已隐藏已延迟优先级为 0 的节点可确认 "majority" 写入操作。

延迟的从节点在所配置的 secondaryDelaySecs 之前无法返回写入确认。

当写入操作使用 w: "majority" 确认返回给客户端后,客户端可使用 "majority" readConcern 来读取该写入操作的结果。

如果为多文档事务指定 "majority" 写关注,并且该事务未能复制到计算出的多数副本集成员,则该事务可能不会立即在副本集成员上回滚。副本集最终将保持一致。事务始终在所有副本集成员上应用或回滚。

请参阅确认行为以了解 mongod 实例何时会确认该写入操作。

<number>

要求确认写入操作已传播到指定数量的 mongod 实例。例如:

w: 1

要求确认写入操作已传播到独立 mongod 或副本集中的主节点。如果主节点在写入操作复制到任一从节点之前退出,则可回滚数据。

警告:如果写操作使用了 { w: 1 } 写关注,则当主节点在写操作完成之前重新启动时,回滚目录可能会排除在 oplog hole 操作之后提交的写操作。

w: 0

要求不确认写入操作。但是,w: 0 可能会向应用程序返回有关套接字异常和网络错误的信息。如果主节点在写入操作复制到任一从节点之前退出,则可回滚数据。

如果您指定了 w: 0 但包含 j: truej: true 则可优先要求独立 mongod 或副本集主节点进行确认。

w 可要求主节点以及所需尽可能多的承载数据的从节点进行确认,从而满足指定的写关注。从节点不需要成为投票成员即可达到写关注阈值。

例如,有一 3 成员副本集,其中包含 1 个主节点和 2 个从节点。指定 w: 2 时要求主节点和某一从节点进行确认。指定 w: 3 时要求主节点和两个从节点均进行确认。

已隐藏已延迟优先级为 0 的节点可确认 w: <number> 写入操作。

延迟的从节点在所配置的 secondaryDelaySecs 之前无法返回写入确认。

请参阅确认行为以了解 mongod 实例何时会确认该写入操作。

<custom write concern name>

要求确认写入操作已传播到满足 settings.getLastErrorModes 中所定义自定义写关注的 tagged 成员。有关示例,请参阅自定义多数据中心写关注

如果自定义写关注仅要求主节点进行确认,且在将写入操作复制到任一从节点之前主节点便已退出,则可回滚数据。

请参阅确认行为以了解 mongod 实例何时会确认该写入操作。

提示

另请参阅:

j 选项会要求 MongoDB 确认写入操作已写入磁盘日志

j

如果为 j: true ,则要求确认已将 mongod 实例(如 w:<value> 中所指定)写入磁盘上日志。j: true 自身并不保证写入操作不会因副本集主节点故障转移而进行回滚。

使用j: true时, MongoDB仅在将请求的节点数(包括主节点 (primary node in the replica set))写入日志后才会返回。 以前,副本集的j: true写关注(write concern)仅要求主节点 (primary node in the replica set)写入日志,而不考虑w: <value>写关注(write concern)。

注意

此选项指定写关注的时间限制(以毫秒为单位)。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" }

例如,考虑以下部署以及各自的默认写关注:

Non-Arbiters
仲裁节点
投票节点
多数投票节点
隐式默认写关注
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" }

w 选项和 j 选项决定 mongod 实例确认写入操作的时间。

独立 mongod 在向内存中应用写入操作后或在写入磁盘上日志后,会确认该写入操作。下表列出独立实例的确认行为以及相关的写关注:

j 未指定
j:true
j:false
w: 1
inMemory
On-disk journal
inMemory
w: "majority"
磁盘日志(如果与日记一起运行
On-disk journal
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

确认要求在内存中进行写入操作。

通常,如果设立了j: false ,则无需将操作写入磁盘上日志。 但是,如果设置了writeConcernMajorityJournalDefault: true ,则即使设立了j: false ,也需要设立操作写入日志。

如果设立了j: falsewriteConcernMajorityJournalDefault: true ,则写入操作将异步写入日志。

  • 在将日志刷新到磁盘之前,设立了w: majority的写入不会被确认为完成。

  • w: majority 无论j设置如何,写入操作都会等待"majority"读取快照完成。 这是因为,如果设立了writeConcernMajorityJournalDefault: true ,则多数读取快照基于多数日志写入。

  • 写入操作向客户端应用程序返回并向w: majority确认后,如果设立了majority读关注(read concern),则应用程序可以读取写入结果。

有关行为详情,请参阅 w: "majority" 行为

w: <number>

副本集的任一承载数据的成员均可参与 w: <数量> 写入操作的写入确认。

下表列出了该成员何时可根据 j 值来确认写入操作:

j 未指定
确认要求在内存中进行写入操作 (j: false)。
j: true
确认时要求对磁盘上日志进行写入操作。
j: false
确认要求在内存中进行写入操作。

注意

已隐藏已延迟优先级为 0 的节点可确认 w: <number> 写入操作。

延迟的从节点在所配置的 secondaryDelaySecs 之前无法返回写入确认。

从MongoDB 8.0开始, { w: "majority" }写入会在大多数承载数据的节点持久写入 oplog 条目后返回确认。然后,节点在从本地 oplog 读取更改时异步应用这些更改。在早期版本中,MongoDB 会等到节点应用写入后才返回确认。

{ w: "majority" } 写入返回确认后,立即对从节点进行查询,可能会在从节点应用写入更改之前从集合中读取数据。

如果您的应用程序从辅助数据库读取并需要立即访问在 { w: "majority" } 写入中所做的更改,请在因果一致的会话中运行这些操作。

使用因果一致的客户端会话时,只有在以下情况下,客户端会话才能保证因果一致性:

  • 关联的读取操作使用 "majority" 读关注,而

  • 关联的写入操作使用 "majority" 写关注。

有关详细信息,请参阅因果一致性

本地数据库不支持写关注。MongoDB 会静默忽略为针对本地数据库中集合的操作所配置的全部写关注。

提示

rs.status() 返回 writeMajorityCount 字段,其中包含计算出的多数性数量。

写关注的多数 "majority" 会按以下值中较小的值来计算:

  • 所有有投票权成员(包括仲裁节点)的 majority 与

  • 所有承载数据的有投票权成员的数量。

警告

如果计算出的 majority 数值等于所有承载数据的投票节点(例如有 3-节点的“主节点-从节点-仲裁节点”部署),写关注 "majority" 可能会超时,或在承载数据的投票节点关闭或无法访问时永不进行确认。如果可能,请使用承载数据的投票节点而不是仲裁节点。

例如,考虑:

  • 具有 3 个投票成员的副本集,即主节点-从节点-从节点 (P-S-S):

    • 所有有投票权成员的 majority 为 2。

    • 所有承载数据的有投票权成员的数量为 3。

    The calculated majority is 2, the minimum of 2 and 3. The write must propagate to the primary and one of the secondaries to acknowledge the write concern "majority" to the client.
  • 具有 3 个有投票权成员(即,主节点-从节点-仲裁节点 (P-S-A))的副本集

    • 所有有投票权成员的 majority 为 2。

    • 所有承载数据的投票成员的数量为 2。

    The calculated majority is 2, the minimum of 2 and 2. Since the write can only be applied to data-bearing members, the write must propagate to the primary and the secondary to acknowledge the write concern "majority" to the client.

    提示

    避免将 "majority" 写关注与 (P-S-A) 或其他要求所有数据承载投票成员都可用来确认写入的拓扑一起使用。希望使用 "majority" 写关注实现持久性保证的客户应改为部署不要求所有数据承载投票成员都可用的拓扑(例如P-S-S)。

警告

要将仲裁节点添加到现有副本集:

在使用具有一个仲裁节点的新副本集之前,您不需要更改集群范围的写关注(write concern)。

从 4.4 版本开始,MongoDB 会跟踪写关注 provenance,而后者表示特定写关注的来源。您可能会在 getLastError 指标中看到 provenance、写关注错误对象和 MongoDB 日志。

下表显示了可能的写关注 provenance 值及其重要性:

来源
说明
clientSupplied
应用程序中指定了写关注。
customDefault
写入关注源自自定义的默认值。请参阅 setDefaultRWConcern
getLastErrorDefaults
写关注源自副本集的 settings.getLastErrorDefaults 字段。
implicitDefault
在没有所有其他写入关注规范的情况下,写入关注源自服务器。

提交法定人数写关注之间有重要区别:

  • 索引构建使用提交法定人数。

  • 写入操作使用写关注。

集群中的每个承载数据的节点均为一个有投票权成员。

提交法定人数指定了必须准备多少个承载数据的有投票权节点,或是哪些有投票权节点(包括主节点)来提交同步索引构建。主节点才会执行提交。

写关注是指确认写入操作已传播到指定数量的实例的级别。

在版本 8.0 中进行了更改:提交法定人数指定了在主节点提交索引构建之前必须有多少个节点准备好完成索引构建。相反,当主节点已提交索引构建时,写关注则指定了在此命令返回成功之前有多少个节点必须复制索引构建操作日志条目。

在以前的版本中,当主节点提交索引构建时,写关注会指定在此命令返回成功之前有多少个节点必须完成索引构建。

后退

"snapshot"