Hi~朋友,关注置顶防止错过消息
Retryable Writes
MongoDB Retryable Wirtes允许MongoDB驱动程序当网络发生故障或者集群发生故障时对写操作自动重试一次。
Retryable Writes的前提
- MongDB必须是分片集群或者副本集群
- 存储引擎必须支持文档级别的锁,比如WiredTiger或者in-memory存储引擎
- MongoDB驱动程序版本必须为3.6
- 集群中的每个MongoDB实例版本必须>=3.6,且featureCompatibilityVersion参数必须>=3.6
如何启用Retry Writes
MonogDB 4.2以后的驱动程序默认是启动了Retryable Writes,更早版本的驱动程序可以通过在连接字符串或配置中设置retryWrites=true参数来启动。
mongosh默认是开启Retryable Writes,可以通过--retryWrites=false进行禁用,如下:
mongosh --retryWrites=false
事务的重试
在MongoDB中,事务的提交和终止都是可重试操作,当遇到错误时,MongoDB 会无视retryWrites选项重试一次操作。
支持重试的写操作
当支持的重试操作设置了write concern时来进行结果确认(也就是write concer不能位{w: 0}),支持的操作如下:
- db.collection.insertOne()
- db.collection.insertMany()
- db.collection.updateOne()
- db.collection.replaceOne()
- db.collection.deleteOne()
- db.collection.remove()并且justOne参数为true
- db.collection.findAndModify()
- db.collection.findOneAndDelete()
- db.collection.findOneAndReplace()
- db.collection.findOneAndUpdate()
- db.collection.bulkWrite()只包含单文档操作的数组集合,即insertOne、updateOne、replaceOne、deleteOne
Retry Writes行为
MongoDB重试写入操作只会重试一次,这有助于解决网络抖动和副本选举期间的问题,但不能解决持续性的网络问题。
当副本集或者分片集群故障时,MongoDB驱动程序会等待serverSelectionTimeoutMS参数设置的时间以后再进行重试,因此对于故障转移时间超过serverSelectionTimeoutMS设置的时间后重试操作将无法成功。
db.serverStatus()返回的transactions包含了关于Retryable Writes 的统计数据。
如果启用了写入重试又对local数据库进行写入,应用程序将会报错,local数据库通常用于存储本地服务器信息和副本集操作日志,不建议对其进行写操作。
MongoDB 6.1版本以后,如果第一次和重试写入操作都发生失败,MongoDB会返回一个NoWritesPerformed标签,但是对于insertMany操作会略有不同:
- 如果所有的的文档都没有insert成功,返回一个带NoWritesPerformed标签的错误信息
- 如果只有部分文档写入成功,返回Error但是不带NoWritesPerformed标签
- 如果所有文档都insert成功,则返回Success
Retryable Reads
MongoDB Retryable Reads可以在查询遇到错误时进行一次重试,有利于解决网络抖动的问题。
Retryable Reads的前提
- MongoDB驱动程序版本必须在4.2以上
- MongoDB实例版本必须在3.6以上
如何启用Retry Reads
MongoDB 4.2以后默认启动了Retry Reads,如果想禁用该功能可以对连接字符串增加retryReads=false。
mongsh不支持Retryable Reads。
支持Retryable的读操作
- Collection.aggregate
- Collection.count
- Collection.countDocuments
- Collection.distinc
- Collection.estimatedDocumentCount
- Collection.find
- Database.aggregate
- Collection.watch
- Database.watch
- MongoClient.watch
- MongoClient.listDatabases
- Database.listCollections
- Collection.listIndexes
Retry Read行为
MongoDB重试写入操作只会重试一次,这有助于解决网络抖动问题,但不能解决持续性的网络问题。
当副本集或者分片集群故障时,MongoDB驱动程序会等待serverSelectionTimeoutMS参数设置的时间以后再进行重试,因此对于故障转移时间超过serverSelectionTimeoutMS设置的时间后重试操作将无法成功。