读取关注点
本readConcern
选项允许您控制从副本集和分片集群读取的数据的一致性和隔离属性。
通过有效使用写关注和读关注,您可以适当地调整一致性和可用性保证的水平,例如等待更强的 consistency 保证,或者放宽一致性要求以提高可用性。
副本集和分片集群支持设置全局默认读关注。未指定显式读关注的操作将继承全局默认读关注设置。有关更多信息,请参阅setDefaultRWConcern
。
读取关注级别
以下读取关注级别可用
级别 | 描述 |
---|---|
查询返回的数据可能未被写入到副本集大多数成员(即可能被回滚)。 可用性:读关注 对于分片集群, 有关更多信息,请参阅 | |
查询返回已由大多数副本集成员确认的数据。由读取操作返回的文档是持久的,即使在发生故障的情况下。 为了满足“多数”读取关注,副本集成员从其数据的大多数提交点的内存视图返回数据。因此,读取关注 可用性 读取关注 要求:要使用 对于多文档事务中的操作,只有在事务以 有关更多信息,请参阅 | |
查询返回反映所有在读取操作开始之前完成的大多数确认写入的数据。查询可能会等待并发执行的写入传播到大多数副本集成员,然后返回结果。 如果在读取操作之后大多数副本集成员崩溃并重新启动,如果将 当将
您不能将 需求 可线性化读取关注点仅适用于读取操作指定一个唯一标识单个文档的查询过滤器。此外,如果以下任何标准都不满足,可线性化读取关注点可能不会从一致的快照中读取,导致与过滤器匹配的文档不被返回 如果满足上述任何标准,则查询将从一致的快照中读取以返回单个匹配的文档。 在多数数据承载成员不可用的情况下,始终使用 有关更多信息,请参阅 | |
具有读取关注点 如果事务不是因果一致性会话的一部分,则事务提交时与写入关注点 "majority" ,则保证事务操作已从多数已提交数据的快照中读取。如果一个事务是因果一致性会话的一部分,在事务提交时使用写关注 "majority" (多数写关注),则事务操作将保证从多数已提交数据的快照中读取,该快照与事务开始前立即执行的操作提供因果一致性。可用性 以下场景可以使用读关注 |
无论读关注级别如何,节点上的最新数据可能不会反映系统中数据的最新版本。
有关每个读关注级别的更多信息,请参阅:
readConcern
支持
读关注选项
对于不在多文档事务中的操作,您可以通过指定选项将读关注级别应用于支持读关注的命令和方法。
readConcern: { level: <level> }
要指定以下操作的读关注级别:mongosh
方法 db.collection.find()
,使用 cursor.readConcern()
方法
db.collection.find().readConcern(<level>)
事务和可用的读关注点
对于 多文档事务,您应在事务级别设置读关注点,而不是在单个操作级别。事务中的操作将使用事务级别的读关注点。在事务内部,任何在集合和数据库级别设置的读关注点都将被忽略。如果显式指定了事务级别的读关注点,事务内部的客户端级别读关注点也将被忽略。
重要
不要显式设置单个操作的读关注点。要设置事务的读关注点,请参阅 读关注点/写关注点/读优先级。
您可以在事务开始时设置读关注点
对于多文档事务,以下读关注点级别可用
作为 多文档事务一部分的写命令可以支持事务级别的读关注点。
您可以在事务内部 创建集合和索引。如果显式创建集合或索引,事务必须使用读关注点
"local"
。如果您隐式创建集合,可以使用事务可用的任何读关注点。
如果在事务开始时未指定,则事务将使用会话级别的读关注点,如果该设置未设置,则使用客户端级别的读关注点。
有关更多信息,请参阅 事务读关注点。
因果一致性会话和可用的读取关注度
对于因果一致性会话中的操作,因果一致性会话,"local"
,"majority"
和"snapshot"
级别都是可用的。然而,为了保证因果一致性,您必须使用"majority"
。有关详细信息,请参阅因果一致性。
支持读取关注度的操作
以下操作支持读取关注度
重要
要为事务中的操作设置读取关注度,您需要在事务级别设置读取关注度,而不是在单个操作级别。不要显式地为事务中的单个操作设置读取关注度。有关更多信息,请参阅事务和读取关注度。
[1] | 您不能将 $out 或 $merge 阶段与读取关注点 "linearizable" 结合使用。也就是说,如果您为 db.collection.aggregate() 指定 "linearizable" 读取关注点,则不能在管道中包含这两个阶段。 |
[2] | 读取关注 "快照" 只适用于某些读取操作和多文档事务。在一个事务中,你无法在分片集合上使用 distinct 命令或其辅助命令。 |
以下写入操作也可以接受读取关注,如果它是多文档事务的一部分
重要
为了设置事务中操作的读取关注,你在事务级别设置读取关注,而不是在单个操作级别。
命令 | |||||
---|---|---|---|---|---|
✓ | ✓ | ||||
✓ | ✓ | ||||
✓ | ✓ | ||||
✓ | ✓ | ||||
✓ | |||||
✓ |
[3] | (1, 2) 读取关注 "快照" 只适用于某些读取操作和多文档事务。对于事务,你在事务级别设置读取关注。支持 "快照" 的事务操作对应于事务中可用的 CRUD 操作。有关更多信息,请参阅 事务和读取关注。 |
在 local
数据库上不支持读取关注
在 local 数据库 上不支持读取关注。MongoDB 默认忽略对本地数据库中集合操作配置的任何读取关注。
注意事项
读取您的写入
如果您请求了写入确认,可以使用 因果一致会话 来读取您的写入。
实时订单
与 "majority" 写入关注点结合使用时,"linearizable" 读取关注点允许多个线程同时对单个文档进行读取和写入,就像一个线程实时执行这些操作一样;也就是说,这些读取和写入的对应调度被认为是线性的。
性能比较
与"majority"
不同,"linearizable"
读关注点会与从节点确认,确保读操作正在从能够与{ w: "majority" }
写关注点确认的副本上读取。[4] 因此,具有线性可读关注点的读取可能比具有"majority"
或"local"
读关注点的读取要慢得多。
在多数数据承载成员不可用的情况下,始终使用 maxTimeMS
与可线性化读取关注点。 maxTimeMS
确保操作不会无限期地阻塞,并且如果读取关注点无法满足,则操作返回错误。
例如
db.restaurants.find( { _id: 5 } ).readConcern("linearizable").maxTimeMS(10000) db.runCommand( { find: "restaurants", filter: { _id: 5 }, readConcern: { level: "linearizable" }, maxTimeMS: 10000 } )
[4] | 在某些情况下,副本集中的两个节点可能暂时认为自己是主节点,但最多只能有一个节点能够使用{ w: "majority" } 写关注点完成写入。能够完成{ w: "majority" } 写入的节点是当前主节点,另一个节点是尚未承认其降级的旧主节点,通常是由于网络分区。在这种情况下,连接到旧主节点的客户端可能会观察到过时的数据,尽管他们请求了primary 读偏好,对旧主节点的新的写入最终将回滚。 |
读操作和afterClusterTime
MongoDB支持因果一致性会话。对于与因果一致性会话关联的读操作,MongoDB支持由驱动程序自动设置与因果一致性会话关联的afterClusterTime读关注点选项。
重要
在进行读取操作时,不要手动设置afterClusterTime
。MongoDB驱动程序会自动为与因果一致性会话相关的操作设置此值。但是,您可以提前操作时间和会话的集群时间,例如与其他客户端会话的操作保持一致。例如,请参阅示例。
注意
不能同时指定atClusterTime
和afterClusterTime
。要使用具有读取关注点"snapshot"
的atClusterTime
,必须禁用因果一致性会话。
为了满足具有afterClusterTime
值为T
的读取请求,mongod
必须在其oplog达到时间T
之后执行请求。如果其oplog尚未达到时间T
,则mongod
必须等待处理请求。
指定了afterClusterTime
的读取操作返回的数据同时满足读取关注点级别要求和指定的afterClusterTime
要求。
对于与因果一致性会话不相关的读取操作,afterClusterTime
未设置。
读取关注点来源
MongoDB跟踪读取关注点provenance
,该provenance指示特定读取关注点的来源。您可以在getLastError
度量标准、读取关注点错误对象和MongoDB日志中看到provenance。
以下表格显示了可能的读取关注点provenance
值及其含义
来源 | 描述 |
---|---|
clientSupplied | 读取关注点是在应用程序中指定的。 |
customDefault | 读取关注级别来自自定义定义的默认值。请参阅 setDefaultRWConcern 。 |
implicitDefault | 在没有其他读取关注级别指定的情况下,读取关注级别来自服务器。 |