阅读隔离度,一致性和新近度

在本页面

Isolation Guarantees

Read Uncommitted

在 MongoDB 中,Client 端可以在写入durable之前查看写入结果:

读未提交是默认的隔离级别,适用于mongod个独立实例以及副本集和分片群集。

读取未提交的单个文档的原子性

对于单个文档,写操作是原子的。即,如果写操作正在更新文档中的多个字段,那么 Reader 将永远不会看到仅更新了某些字段的文档。

使用独立的mongod实例,可以序列化对单个文档的一组读取和写入操作。对于副本集,在没有回滚的情况下,对单个文档的一组读取和写入操作可以序列化。

但是,尽管 Reader 可能看不到部分更新的文档,但未提交的阅读意味着并发的 Reader 仍可以在更改为durable之前看到更新的文档。

未提交读和多文档写

当单个写入操作修改多个文档时,每个文档的修改都是原子的,但是整个操作不是原子的,其他操作可能会交错。

在不隔离多文档写入操作的情况下,MongoDB 表现出以下行为:

  • 非时间点读取操作。假设读取操作在时间* t * 1 开始并开始读取文档。然后,写操作将在以后的某个时间* t * 2 提交对其中一个文档的更新。Reader 可能会看到文档的更新版本,因此看不到数据的时间点快照。

  • 不可序列化的操作。假设读取操作在时间* t * 1 读取文档* d * 1,而写入操作在以后的时间* t * 3 更新* d 1.这引入了读写依赖性,使得如果操作是如果要序列化,则读操作必须在写操作之前。但还假设写操作在时间 t * 2 处更新文档* d * 2,而读操作随后在以后的* t * 4 处读取* d 2.这引入了写-读依赖性,这将需要读操作将在可序列化计划中的写操作之后之后进行。有一个依赖周期,使可序列化成为不可能。

  • 读取操作可能会丢失在读取操作过程中更新的匹配文档。

Cursor Snapshot

在某些情况下,MongoDB 游标可以多次返回同一文档。当游标返回文档时,其他操作可能会与查询交错。如果其中某些操作是updates,它们导致文档移动(对于 MMAPv1,是由于文档增长引起的)或更改了查询所使用的索引上的索引字段;那么光标将多次返回同一文档。

如果您的集合中有一个或多个从未修改过的字段,则可以在此字段或这些字段上使用* unique *索引,以便查询将不超过一次的返回每个文档。使用hint()查询可显式强制查询使用该索引。

Monotonic Writes

默认情况下,MongoDB 为独立的mongod实例和副本集提供单调写保证。

有关单调写入和分片群集,请参见Causal Consistency

实时订单

3.4 版的新功能。

对于主服务器上的读取和写入操作,发出具有"linearizable"读取关注事项的读取操作和具有"majority"写入关注事项的写入操作,使多个线程可以在单个文档上执行读写操作,就好像单个线程实时地执行了这些操作一样;也就是说,这些读写的相应计划被认为是线性的。

Causal Consistency

3.6 版的新功能。

如果操作在逻辑上取决于先前的操作,则这些操作之间存在因果关系。例如,基于指定条件删除所有文档的写入操作和验证删除操作的后续读取操作具有因果关系。

在因果一致的会话中,MongoDB 以尊重其因果关系的 Sequences 执行因果操作,并且 Client 观察到与因果关系一致的结果。

Client 会话和因果一致性保证

为了提供因果一致性,MongoDB 3.6 在 Client 端会话中启用因果一致性。因果一致的会话表示具有"majority"读关注点的读操作和具有"majority"写关注点的写操作的关联序列具有因果关系,这由它们的 Sequences 反映出来。 应用程序必须确保一次在 Client 端会话中一次仅执行一个线程.

对于因果相关的操作:

  • Client 端启动 Client 端会话。

Important

Client 会话仅保证以下方面的因果一致性:

  • 使用"majority"读取操作;即返回数据已被大多数副本集成员确认并且是持久的。

  • "majority"写关注的写操作;即要求确认该操作已应用于大多数副本集投票成员的写入操作。

有关因果一致性和各种读写问题的更多信息,请参见因果一致性和读写问题

  • 当 Client 端发出具有"majority"读关注和写操作(具有"majority"写关注)的读取 Sequences 时,Client 端将在每个操作中包括会话信息。

  • 对于与会话相关联的每个具有"majority"读关注度的读取操作和具有"majority"写关注度的写入操作,即使操作出错,MongoDB 也会返回操作时间和集群时间。Client 端会话跟踪操作时间和群集时间。

Note

MongoDB 不返回未确认(w: 0)写入操作的操作时间和群集时间。未经确认的写入并不表示任何因果关系。

尽管 MongoDB 在 Client 端会话中返回读取操作和已确认的写入操作的操作时间和群集时间,但是只有具有"majority"读取关注点的读取操作和具有"majority"写入关注点的写入操作才能保证因果一致性。有关详细信息,请参见因果一致性和读写问题

  • 关联的 Client 端会话跟踪这两个时间字段。

Note

不同会话之间的操作可以因果一致。 MongoDB 驱动程序和mongo shell 提供了用于延长 Client 端会话的操作时间和集群时间的方法。因此,Client 端可以提前群集时间和一个 Client 端会话的操作时间,使其与另一 Client 端会话的操作保持一致。

因果一致性保证

下表列出了因果一致性会话为具有"majority"读关注点的读取操作和具有"majority"写关注的写操作提供的因果一致性保证。

GuaranteesDescription
阅读您的文章读操作反映了在其之前的写操作的结果。
Monotonic reads读取操作不会返回与先前读取操作相比更早的数据状态的结果。


例如,如果在会话中:
write1 优先于 write2,
read1 在 read2 之前,并且
read1 返回反映 write2 的结果
那么 read2 无法返回 write1 的结果。
|单语写|必须在其他写之前执行的写操作在其他写之前执行。
例如,如果在会话中 write1 必须在 write2 之前,则 write2 时的数据状态必须反映出 write1 数据的状态。其他写入可以在 write1 和 write2 之间进行交错,但是 write2 不能在 write1 之前发生。
| Writes 跟在 reads | Write 操作之后,而这些操作在执行 read 操作之后必须执行。也就是说,写入时的数据状态必须包含先前读取操作的数据状态。

Read Preference

这些保证适用于 MongoDB 部署的所有成员。例如,如果在因果一致的会话中发出具有"majority"写入关注点的写入,然后发出从具有"majority"读取关注点的辅助节点(即读取首选项<secondary>)读取的读取,则读取操作将反映数据库的状态。写操作。

Isolation

因果一致的会话内的操作与会话外的操作不是隔离的。如果并发的写操作在会话的写操作和读操作之间交错,则会话的读操作可能返回反映在会话的写操作之后*发生的写操作的结果。

功能兼容版本

featureCompatibilityVersion(fCV)必须设置为“ 3.6”或更大。要检查 fCV,请运行以下命令:

db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

有关更多信息,请参见View FeatureCompatibilityVersionsetFeatureCompatibilityVersion

MongoDB Drivers

Tip

应用程序必须确保一次只有一个线程在 Client 端会话中执行这些操作。

Client 端需要为 MongoDB 3.6 或更高版本更新的 MongoDB 驱动程序:

Java 3.6+

Python 3.6+
C 1.9
C#2.5
Node 3.0+
Ruby 2.5
Perl 2.0
PHPC 1.4+
Scala 2.2+

Limitations

以下构建内存结构的操作在因果上不一致:

OperationNotes
collStats
$collStatslatencyStats选项。
$currentOp如果操作与因果一致的 Client 端会话相关联,则返回错误。
dbStats
getMore如果操作与因果一致的 Client 端会话相关联,则返回错误。
$indexStats
ping如果操作与因果一致的 Client 端会话相关联,则返回错误。
serverStatus如果操作与因果一致的 Client 端会话相关联,则返回错误。
createIndexbackground: true选项;即背景索引构建