MongoDB Manual (Version 4.2)> MongoDB CRUD Operations > MongoDB CRUD Concepts > Read Isolation, Consistency, and Recency
在本页面中我们将了解:
隔离性保证
单调写入
实时顺序
因果一致性
隔离性保证
读未提交
根据设置的读关注,客户端可以在写入被持久化之前看到写入的结果:
不考虑一个写操作的写关注,其他客户端使用
local
或者available
的读关注级别都可以看到写操作的结果。使用
local
或available
读取关注级别的客户端可以读取数据,这些数据随后可能会在副本集故障转移期间回滚。
对于多文档事务中的操作,当事务提交时,在事务中进行的所有数据更改都将保存并在事务外部可见。也就是说,一个事务在回滚其他事务时将不会提交其某些更改。
在提交事务之前,在事务外部看不到在事务中进行的数据更改。
但是,当事务写入多个分片时,并非所有外部读取操作都需要等待已提交事务的结果在所有分片上可见。例如,如果提交了一个事务,并且在分片A上可以看到写1,但是在分片B上还看不到写2,则外部一个读关注级别为local
的读操作可以读取写1的结果而看不到写2。
读未提交是默认的隔离级别,适用于mongod独立实例以及副本集和分片群集。
读未提交与单文档原子性
对于单个文档,写操作是原子性的。即,如果写操作正在更新文档中的多个字段,则读操作将永远不会看到仅更新了某些字段的文档。但是,尽管客户端可能看不到部分更新的文档,但读未提交意味着并发读取操作仍可以在使更改持久之前看到更新的文档。
对于以独立模式部署的 mongod
实例,对单个文档的一组读写操作是线性的。使用副本集时,只有在没有回滚的情况下,对单个文档的一组读取和写入操作才是线性的。
读未提交与多文档写入
当单个写入操作(例如db.collection.updateMany()
)修改多个文档时,每个文档的修改都是原子的,但整个操作不是原子的。
当执行多文档写操作时,无论是通过单个写操作还是通过多个写操作,其他操作都可能会交错。
对于需要原子性地读写多个文档(在单个或多个集合中)的情况,MongoDB支持多文档事务:
4.0版本中,MongoDB支持副本集内的多文档事务。
4.2版本中,MongoDB引入了分布式事务,从而增加了对分片群集上多文档事务的支持,并结合了对副本集上多文档事务的现有支持。
关于MongoDB事务的细节,请参考事务。
重要
在大多数情况下,与单文档写入相比,多文档事务产生的性能成本更高,并且多文档事务的可用性并不能替代有效的架构设计。在许多情况下,非结构化化数据模型(嵌入式文档和数组) 将继续是您的数据和用例的最佳选择。也就是说,在许多情况下,适当地对数据建模将最大程度地减少对多文档交易的需求。
关于其他事务使用方面的注意事项(比如运行时显示和oplog大小限制等),请参考生产注意事项。
在不隔离多文档写入操作的情况下,MongoDB表现出以下行为:
非时间点(
Non-point-in-time
)读取操作。假设读取操作在时间t1开始并开始读取文档。然后,写操作在稍后的某个时间t2提交对其中一个文档的更新。读操作可能会看到文档的更新后版本,因此看不到数据的point-in-time快照。非可序列化的操作。假设读取操作在时间t1读取文档d1,而写入操作在稍后的时间t3更新d1。这引入了读写依赖性,因此,如果要序列化操作,则读取操作必须先于写入操作。但是还假设写操作在时间t2更新文档d2,而读取操作随后在