可重试写入
可重试写入允许 MongoDB 驱动程序在网络错误的情况下自动重试某些写入操作一次,或者如果它们无法在副本集或分片集群中找到健康的主节点。主节点在 副本集或分片集群中。
先决条件
可重试写操作的要求
- 支持的部署拓扑
- 可重试写操作需要副本集或分片集群,并且不支持独立实例。
- 支持的存储引擎
- 可重试写操作需要支持文档级锁定的存储引擎,例如WiredTiger或内存存储引擎。
- 3.6+ MongoDB 驱动程序
客户端需要MongoDB 3.6或更高版本的驱动程序
Java 3.6+
Python 3.6+
C 1.9+
Go 1.8+
C# 2.5+
Node 3.0+
Ruby 2.5+
Rust 2.1+
Swift 1.2+
Perl 2.0+
PHPC 1.4+
Scala 2.2+
C++ 3.6.6+
- MongoDB 版本
- 集群中每个节点的MongoDB版本必须为
3.6
或更高,并且集群中每个节点的featureCompatibilityVersion
必须为3.6
或更高。有关featureCompatibilityVersion
标志的更多信息,请参阅setFeatureCompatibilityVersion
。 - 写确认
- 带有
0
写关注的写操作不可重试。
可重试写操作和多文档事务
事务提交和中止操作是可重试写操作。如果提交操作或中止操作遇到错误,MongoDB驱动程序会重试操作一次,无论是否将retryWrites
设置为false
。
事务内的写操作不可单独重试,无论 retryWrites
的值如何。
有关事务的更多信息,请参阅 事务。
启用可重试写操作
- MongoDB 驱动程序
- 与 MongoDB 4.2 及更高版本兼容的驱动程序默认启用可重试写操作。较早的驱动程序需要
retryWrites=true
选项。对于使用与 MongoDB 4.2 及更高版本兼容的驱动程序的应用程序,可以省略retryWrites=true
选项。要禁用可重试写操作,使用 MongoDB 4.2 及更高版本兼容的驱动程序的应用程序必须在连接字符串中包含retryWrites=false
。 mongosh
mongosh 默认启用可重试写操作。要禁用可重试写操作,请使用
--retryWrites=false
命令行选项。mongosh --retryWrites=false
可重试写操作
以下写操作在具有确认写关注时可以重试;例如,写关注 不能是 {w: 0}
。
注意
事务内的写操作不可单独重试。
方法 | 描述 |
---|---|
插入操作 | |
单文档更新操作 | |
单文档删除操作 | |
findAndModify 操作。所有 findAndModify 操作都是单文档操作。 | |
仅包含单文档写操作的批量写操作。可重试的批量操作可以包含指定的写操作的任何组合,但不能包含任何多文档写操作,例如 updateMany 。 | |
仅包含单文档写操作的批量写操作。可重试的批量操作可以包含指定的写操作的任何组合,但不能包含任何多文档写操作,例如指定 true 为 multi 选项的 update 。 |
行为
持久性网络错误
MongoDB 可重试写操作仅尝试 一次 重试。这有助于解决短暂的网络错误和 副本集选举,但不能解决持久性网络错误。
故障转移期间
如果驱动程序在目标副本集或分片集群分片中找不到健康的主节点,驱动程序将在重试之前等待serverSelectionTimeoutMS
毫秒以确定新的主节点。可重试写操作不解决故障转移期间超过serverSelectionTimeoutMS
的情况。
警告
如果在写入操作后超过localLogicalSessionTimeoutMinutes
分钟,客户端应用程序暂时无响应,那么当客户端应用程序开始响应(无需重启)时,可能会重试并再次应用写入操作。
诊断
serverStatus
命令及其mongosh
shell辅助程序db.serverStatus()
在transactions
部分包含可重试写入的统计信息。
对本地数据库的可重试写入
官方MongoDB驱动程序默认启用可重试写入。写入到本地
数据库的应用程序将会遇到写入错误,除非明确禁用可重试写入。
要禁用可重试写入,请在MongoDB集群的retryWrites=false
连接字符串中指定。
错误处理
从MongoDB 6.1版本开始,如果可重试写入的第一和第二次尝试都失败而没有执行任何写入操作,MongoDB将返回带有NoWritesPerformed
标签的错误。
NoWritesPerformed
标签区分了像insertMany()
这样的批量操作的结果。在insertMany
操作中,可能发生以下情况
结果 | MongoDB输出 |
---|---|
没有插入文档。 | 返回带有 NoWritesPerformed 标签的错误。 |
部分工作完成。(至少插入了一个文档,但不是全部。) | 返回不带 NoWritesPerformed 标签的错误。 |
所有文档都插入了。 | 返回成功。 |
应用程序可以使用NoWritesPerformed
标签来确定没有插入任何文档。这种错误报告让应用程序在处理可重试写入时保持数据库状态的准确性。
在MongoDB的早期版本中,如果可重试写入的第一和第二次尝试都失败,将返回错误。但是,没有区分来指示没有执行写入操作。