深入浅出MongoDB(五)
文章目录
可重试读取
- 可重试读取允许mongodb驱动程序在遇到某些网络或服务器错误时,自动重试某些读取操作一次。只有连接到mongodb server 3.6或更高版本时,驱动程序才能重试读取操作。
- 与mongodb server 4.2及更高版本兼容的官方驱动默认启用了可重试读取功能,要显式禁用可重试读取,在部署的连接字符串指定
retryReads=false
,mongosh
不支持可重试读取。 - mongodb驱动程序支持重试以下读操作
shell
# CRUD API读操作
Collection.aggregate
Collection.count
Collection.countDocuments
Collection.distinct
Collection.estimatedDocumentCount
Collection.find
Database.aggregate
# 变更流操作
Collection.watch
Database.watch
MongoClient.watch
# 枚举操作
MongoClient.listDatabases
Database.listCollections
Collection.listIndexes
# GridFS文件下载操作
GridFSBucket.openDownloadStream
- 不支持可重试读取的操作
shell
db.collection.mapReduce()
getMore
任何读取命令都会传递给通用Database.runCommand帮助程序,该程序与读取或写入命令无关
- mongodb可重试读取仅进行一次重试操作,有助于解决暂时性网络错误或副本集选举,但不能解决持续性网络错误。
可重试写入
- 可重试写入允许mongodb驱动程序在遇到网络错误或者在副本集或分片集群中找不到健康的主节点时自动重试某些写入操作。
- 可重试写入需要副本集或者分片集群,不支持独立实例;需要支持文档级锁定的存储引擎,比如WiredTiger或内存存储引擎;需要mongodb 3.6或更高版本的驱动程序;mongodb版本需要3.6及以上版本;写关注为0时发出的写入操作不可重试。
- 可重试写入和多文档事务,事务提交和中止操作是可重试的写入操作。如果提交操作或中止操作遇到错误,则不管
retryWrites
是否设置为false,mongodb驱动程序都会重试该操作一次。 - 启用可重试写入,与mongodb 4兼容的驱动程序,2及更高版本默认启用可重试写入,早起的驱动程序需要
retryWrites=true
选项。可重试写入默认在mongosh
中启用,要禁用可重试写入使用--retryWrites=false
命令行选项。默认情况下在旧版mongo
中禁用可重试写入,可以使用--retryWrites=true
启用可重试写入。 - 可重试写入操作,当以确认写发出时,以下写入操作是可重试的,例如写关注不能为
{w: 0}
。
shell
# 插入操作
db.collection.insertOne()
db.collection.insertMany()
# 单个文档变更操作
db.collection.updateOne()
db.collection.replaceOne()
# 单个文档删除操作
db.collection.deleteOne()
db.collection.remove()
# findAndModify操作
db.collection.findAndModify()
db.collection.findOneAndDelete()
db.collection.findOneAndReplace()
db.collection.findOneAndUpdate()
# 仅单文档写入操作的批量写入操作,可重试的批量操作可以包括指定写入操作的任意组合
db.collection.bulkWrite(): insertOne、updateOne、replaceOne、deleteOne
# 批量写入操作只包括单文档写入操作
Bulk.find.removeOne()
Bulk.find.replaceOne()
Bulk.find.updateOne()
读关注
- 借助readConcern选项,我们可以控制从副本集和分片集群读取的数据的一致性和隔离属性。通过有效使用写关注和读关注,我们可以适当调整一致性和可用性保证的级别,比如等待更强的一致性保证,或者放松一致性要求以提供更高的可用性。副本集和分片集群支持设置全局默认的读关注。未指定显式读关注的操作会继承全局默认的读关注设置。
- 读关注级别
level | 说明 |
---|---|
local | 查询从实例返回数据,不保证数据已写入副本集的多数成员,针对主节点和从节点默认读取。无论有没有因果一致的会话和事务,均可使用local。 |
available | 查询从实例返回数据,不保证数据已写入副本集的多数成员,不能与因果一致的会话和事务结合使用。对于分片集群,avaiable在各种读关注中提供最低延迟读取,会牺牲一致性。 |
majority | 查询返回已被副本集多数成员确认的数据,即使失败,读取操作返回的文档也是持久性的。为了保证读关注多数,副本集成员在多数提交点从其内存数据视图返回数据。无论有没有因果一致的会话和事务都可以使用。副本集必须是WiredTiger存储引擎。 |
linearizable | 该查询返回的数据反映了在读取操作开始之前完成的所有成功的多数已确认的写入操作。该查询可能会等待并发执行的写入操作的数据复制到多数副本集成员之后,再返回结果。如果多数副本集成员在读操作后崩溃并重新启动,且 writeConcernMajorityJournalDefault设置为默认状态 true ,则读操作返回的文档是持久化的。将 writeConcernMajorityJournalDefault设置为 false 时,MongoDB 不会等待 w: "majority"写入在写入到磁盘日志后才确认写入。 |
snapshot | 查询会返回最近某个特定时间点跨分片出现的多数提交数据。当事务以写关注majority提交时,读关注snapshot才提供保证。 |
readConcern支持
- 读关注选项,对于不在多文档事务中的操作,可以把readConcern级别指定为支持读关注的命令和方法的选项。
shell
readConcern: { level: <level> }
db.collection.find().readConcern(<level>)
- 对于多文档事务,我们可以在事务级别设置读关注,而不是在单个操作级别。事务中的操作将使用事务级读关注。在集合和数据库级别设置的任何读关注在事务中都会被忽略。如果显式指定了事务级读关注,则在事务内也会忽略客户端级读关注。
- 我们可以在事务开始时设置读关注。对于多文档事务,可以关注local、majority和snapshot读关注级别;归属多文档事务的写命令可以支持事务级读关注;可以在事务中创建集合和索引,如果显式创建集合或索引,则事务必须使用读关注local,如果隐式创建集合,则可以使用任何可用于事务的读关注。
- 对于因果一致性的会话,我么可以使用local、majority和snapshot级别的读关注,为了保证因果一致性,我们必须使用majority。
- 支持读关注的操作,要为事务中的操作设置读关注,在事务级别而非单个操作级别设置读关注。
方法 | local | available | majority | snapshot | linearizable |
---|---|---|---|---|---|
count | ☑️ | ☑️ | ☑️ | ☑️ | |
distinct | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
find | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
db.collection.find()(通过cursor.readConcern()) | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
getMore | ☑️ | ☑️ | |||
aggregate | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
Session.startTransaction() | ☑️ | ☑️ | ☑️ |
- local数据库不支持读关注,mongodb默认忽略对本地数据库中集合操作的任何配置的读关注。
写关注
- 写关注说明了mongodb为针对独立运行的mongod、副本集或分片集群的写入操作所请求的确认级别。在分片集群中,mongos实例会将写关注传递给分片。
- 写关注说明
shell
# w选项会请求确认写入操作已传播到指定数量的mongod实例或带有指定标签的mongod实例
# j选项以请求确认写入操作已写入磁盘日志,w和j选项决定mongod实例确认写入操作的时间
# wtimeout选项用于指定时间限制,防止写入操作无限期阻塞
{w: <value>, j: <boolean>, wtimeout: <number>}
- 从mongodb 5.0开始,隐式默认写关注为
w: majority
,针对包含仲裁节点的部署则有特殊考虑。