读关注 在本页面

    读关注 选项允许你控制从复制集和分片集群读取数据的一致性和隔离性。

    通过有效地使用写关注和读关注,你可以适当地调整一致性和可用性的保证级别,例如等待以保证更强的一致性,或放松一致性要求以提供更高的可用性。

    将MongoDB驱动程序更新到MongoDB 3.2或更高版本以支持读关注。

    阅读关注级别 以下为可用的读关注级别:

    level Description
    "local" 查询并从实例返回数据,但不能保证该数据已被写入大多数副本集成员(即可能已经回滚)。

    默认为:
    针对主节点读。
    如果读取与因果一致的会话相关联,则针对副节点读。

    可用性:读关注local可用于有或没有因果关系一致的会话和事务中。

    更多的信息,请参考"local"
    "available" 查询并从实例返回数据,但不能保证该数据已被写入大多数副本集成员(即可能已经回滚)。

    默认为:如果读取与因果关系一致的会话没有关联,则针对副节点读

    可用性:读关注available无法用于有因果关系一致的会话和事务中。

    对于分片群集,"available"读关注提供了各种读关注中尽可能最低的延迟。但是,这是以牺牲一致性为代价的,因为从分片的集合中进行读取时,"available"读关注会返回孤立的文档。为了避免从分片的集合中读取时返回孤立文档的风险,可使用其他读关注,如"local"读关注。

    更多的信息,请参考"available"

    3.6版本的新功能
    "majority" 为了满足读关注“majority”,副本集成员从其内存视图中返回多数提交点提交的数据。这样,读关注"majority"在性能成本上可与其他读关注相媲美。

    可用性:
    读关注"majority"可用于有或没有因果关系一致的会话和事务中。
    对于具有三名成员的主从仲裁(PSA)架构的部署,可以禁用读关注"majority";但是,这对change streams(仅在MongoDB 4.0和更早版本中)和分片群集上的事务有影响。有关更多信息,请参见禁用读关注Marjority.。
    要求:若要使用"majority"读关注级别,副本集必须使用WiredTiger存储引擎。

    注意:
    对于多文档事务中的操作,仅当事务以写关注"majority"提交时,读关注"majority"才提供其保证。否则,"majority"读关注不能保证其在事务中读取的数据。

    更多的信息,请参考"majority"
    "linearizable" 该查询返回的数据表示了这些数据在操作开始之前已成功在大多数节点确认写入。查询可能会等待并发执行的写操作传播到大多数副本集成员,然后返回结果。
    如果大多数副本集成员崩溃并在读操作后重新启动,则如果将writeConcernMajorityJournalDefault设置为默认状态true,则读操作返回的文档将还是有效的。
    writeConcernMajorityJournalDefault设置为false时,MongoDB不会等待w: "majority"在确认写入之前先要写入磁盘日志。这样,如果给定副本集中大多数节点的瞬时丢失(例如崩溃和重新启动),majority写操作可能会回滚。
    可用性:
    读关注"linearizable"不适用于因果一致的会话和事务。
    你可以仅对主节点上的读操作指定为线性读关注。
    你不能将$out$merge操作与读关注"linearizable"结合使用。也就是说,如果为db.collection.aggregate()指定为"linearizable"读关注,则不能在管道中使用任何的操作。

    要求:linearizable读关注仅保证在读操作指定了唯一标识单个文档的查询过滤器时可用。

    请始终将maxTimeMS与linearizable读关注一起使用,以防止大多数数据承载成员不可用。maxTimeMS确保操作不会无限期地阻塞,而是确保如果无法满足读取要求,则操作将返回错误。
    更多的信息,请参考"linearizable"
    "snapshot" 如果事务不是因果一致会话的一部分,写关注为"majority"且在事务提交后,可以确保事务操作已从多数提交数据的快照中读取。
    如果事务是因果一致会话的一部分,写关注为"majority"且在事务提交后,可以确保事务操作已从多数提交数据的快照中读取,该快照提供了与紧接事务开始之前的操作的因果一致性。
    读关注"snapshot"仅可用于多文档事务。
    对于分片群集上的事务,如果事务中的任何操作涉及已被禁用读关注“majority”的分片,那你就不能对该事务使用读关注"snapshot"。你只能对事务使用读关注"local""majority"

    无论读关注级别如何,节点上的最新数据都可能无法反映系统中数据的最新版本

    有关每个阅读关注级别的更多信息,请参见:

    对于不在多文档事务中的操作,你可以将 readConcern 级别指定为一个命令和方法的选项:

    1. readConcern: { level: <level> }

    要为 mongo shell方法 db.collection.find() 指定阅读关注级别,请使用 cursor.readConcern() 方法:

    1. db.collection.find().readConcern(<level>)

    事务和可用的读关注

    对于多文档事务,应在事务级别而不是在单个操作级别设置读关注。事务中的操作将使用事务级别的读关注。事务内部将忽略在集合和数据库级别设置的任何读关注。如果显式指定了事务级别的读关注点,则在事务内部也将忽略客户端级别的读关注点。

    重要

    不要为各个操作明确设置读关注。要设置事务的读关注,请参阅读 Read Concern/Write Concern/Read Preference

    你可以在事务开始时设置读关注:

    如果未在事务开始时指定,则事务将使用会话级的读关注,或者如果未设置,则使用客户端级的读关注。

    有关等多信息,请参考 事务的读关注.

    因果一致的会话和阅读相关的担忧

    对于在因果一致的会话中的操作,"local" h和 "majority"级别可用。但是,为了保证因果一致性,你必须使用 "majority"。有关详细信息,请参见 因果一致性

    如果多文档事务与因果一致的会话相关联,则"snapshot" 也可用于该事务。

    支持读关注的操作 下列的操作支持读关注:

    重要

    在为事务中的操作设置读关注时,请在事务级别而不是在单个操作级别设置读关注。不要在事务中明确的设置单独操作的读关注。更多信息,查看事务和读关注

    命令/方法 "local" "available" "majority" "snapshot" "linearizable"
    count
    distinct
    find
    db.collection.find() via cursor.readConcern()
    geoSearch
    getMore
    aggregate db.collection.aggregate()
    Session.startTransaction()
    [1] 你不能将$out 或者 $merge阶段与读关注的"linearizable"结合使用。也就是说,如果为db.collection.aggregate()指定"linearizable"读关注,则不能在管道中包括任何一个阶段。
    [2] 读关注"snapshot"仅适用于多文档事务。在事务中,不能在分片集合上使用distinct命令或其协助命令。

    下列的写操作页能接受读关注,但必须是多文档事务的一部分:

    重要

    在为事务中的操作设置读关注时,请在事务级别而不是在单个操作级别设置读关注

    Command 命令 "local" "available" "majority" "snapshot" "linearizable"
    delete
    db.collection.deleteMany()
    db.collection.deleteOne()
    db.collection.remove()
    findAndModify
    db.collection.findAndModify()
    db.collection.findOneAndDelete()
    db.collection.findOneAndReplace()
    db.collection.findOneAndUpdate()
    insert
    db.collection.insert()
    db.collection.insertOne()
    db.collection.insertMany()
    update
    db.collection.update()
    db.collection.updateMany()
    db.collection.updateOne()
    db.collection.replaceOne()
    [3] (1, 2)读关注“SNAPSHOT”仅适用于多文档事务,并且对于事务,您可以在事务级别设置读关注。支持“SNAPSHOT”的操作对应于事务中可用的CRUD操作。有关更多信息,请参见事务和读关注

    注意事项 读自己的文章 在版本3.6中更改

    从MongoDB 3.6版本开始,如果写请求确认,你可以使用因果一致的会话读你自己写入的内容。

    在MongoDB 3.6之前,您必须使用 { w: "majority" } 写关注发出写操作,然后对读操作使用 "majority" 或者 "linearizable"读关注,以确保单个线程可以读取自己的写入内容

    实时顺序 结合"majority" 写关注,"linearizable" 读关注使多个线程可以在单个文档上执行读写操作,就好像单个线程实时地执行了这些操作一样。 也就是说,这些读写的对应的计划被认为是线性的。

    性能比较 与"majority"不同,"linearizable" 的读关注通过从节点确认读操作正在从主节点读,该操作能够以{ w: "majority" }写关注来确认写入。 [4]因此,具有线性化读关注的读取可能比具有"majority""local"读关注的读慢得多。

    为了避免万一大多数数据承载成员不可用,请始终将 maxTimeMS 与可线性化的读确认一起使用。maxTimeMS 确保操作不会无限期地阻塞,而是确保如果无法满足读取要求,则操作将返回错误。

    例如:

    1. db.restaurants.find( { _id: 5 } ).readConcern("linearizable").maxTimeMS(10000)
    2. db.runCommand( {
    3. find: "restaurants",
    4. filter: { _id: 5 },
    5. readConcern: { level: "linearizable" },
    6. maxTimeMS: 10000
    7. } )
    [4] 某些情况下,副本集中的两个节点可能会短暂地认为它们是主节点,但至多,其中一个节点将能够以{ w: "majority" }写关注完成。 可以完成{ w: "majority" }写入的节点是当前主节点,另一个节点是前主节点,由于网络分区的原因,该主节点尚未意识到其降级。 发生这种情况时,尽管请求的读优先级为主节点,但连接到前主界定啊的客户端仍可能会读到过时的数据,并且最终将对前主节点新写入的进行回滚。

    读操作和afterClusterTime 3.6 版本新加入

    MongoDB 3.6引入了对因果一致会话的支持。 对于与因果一致的会话相关联的读操作,MongoDB 3.6引入了 afterClusterTime 读关注选项,驱动程序会自动将afterClusterTime 读关注选项设置为与因果一致的会话相关联的操作。

    [warning] 重要

    不要手动为读操作设置 afterClusterTime 。 MongoDB驱动程序会针对与因果一致的会话相关联的操作自动设置此值。 但是,您可以提前会话的操作时间和群集时间,以便与另一个客户端会话的操作保持一致。 有关示例,请参见示例

    为了满足 afterClusterTime 值为T的读请求, mongod 必须在其oplog到达时间T之后执行请求。如果其oplog尚未达到时间T,则 mongod 必须等待服务该请求。

    使用指定的 afterClusterTime 的读操作将返回满足读关注级别要求和指定的 afterClusterTime 要求的数据。

    对于与因果一致会话无关的读操作,未设置 afterClusterTime

    阅读问题出处

    从4.4版本开始,MongoDB跟踪阅读关注来源,表示某个特定读取关注点的来源。您可能会在getLastError指标、读取关注错误对象和MongoDB日志中看到出处。

    下表显示了可能的阅读问题provenance值及其重要性:

    出处 描述
    clientSupplied read关注点是在应用程序中指定的。
    customDefault 读取关注点源自自定义的默认值。 参见 setDefaultRWConcern.
    implicitDefault 在没有其他所有读取关注规范的情况下,读取关注源自服务器。

    译者:杨帅 张琦

    校对:杨帅

    参见

    原文 - Read Isolation (Read Concern)