FAQ: MongoDB并发
在本页面
MongoDB允许多个客户端读取和写入相同的数据。为了确保一致性,它使用锁定和其他 并发控制措施来防止多个客户端同时修改同一数据。这 些机制共同保证了对单个文档的所有写入全部发生或完全不发生,并且客户端永远不会看到不一致的数据视图。
MongoDB使用读-写锁,允许并发的读写操作以共享的方式访问资源(例如数据库或集合)。
除了用于读取的共享(S)锁定模式和用于写操作的排他(X)锁定模式之外,意向共享(IS)和意向排他(IX)模式还表明使用更精细的锁定粒度来读取或写入资源的意图 。当以一定的粒度锁定时,所有更高级别的锁定都使用意向锁来锁定。
例如,当锁定用于写的集合(使用排它X锁定模式)时,必须同时在意向排他(IX)锁定模式下锁定相应的数据库锁和全局锁。单个数据库可以同时在IS和IX模式下锁定,但是独占(X)锁不能与任何其他模式共存,共享(S)锁只能与意向共享(IS)锁共存。
锁是公平的,读取和写入按顺序排队。但是,为了优化吞吐量,当一个请求被授予时,所有其他兼容请求将同时被授予,从而有可能在冲突请求之前释放它们。例如,考虑X锁(排它锁)被释放的情况,并且冲突队列包含以下各项:
IS → IS → X → X → S → IS
在严格的先进先出(FIFO)顺序中,将仅授予前两个IS模式。相反,MongoDB实际上将授予所有IS和S模式,一旦它们全部完成,它将授予X,即使在此期间新的IS或S请求已进入排队。由于授予将始终将所有其他请求移到队列中,因此任何请求都不会存在饿死等待问题。
锁模式 | Description |
---|---|
R | 代表共享锁(S) |
W | 代表排它锁(X) |
r | 代表意向共享锁 (IS) |
w | 代表意向排它锁 (IX) |
对于大多数读取和写入操作,WiredTiger使用乐观并发控制。WiredTiger仅在全局,数据库和集合级别使用意向锁。当存储引擎检测到两个操作之间存在冲突时,将引发写冲突,从而导致MongoDB对用户而言透明地重试该操作。
要报告有关锁的锁使用率信息,请使用以下任何一种方法:
锁定模式 | 描述 |
---|---|
R | 表示共享(S)锁。 |
W | 表示排他(X)锁。 |
r | 表示共享意图(IS)锁。 |
w | 表示意向排他(IX)锁。 |
在某些情况下,读和写操作可以产生它持有的锁。
- 避免长时间执行的存储性事务,因为这些事务可能需要在内存中保存大量数据;
- 作为中断响应点(interruption points),以便您可以取消长时间运行的操作;
- 允许需要排他访问集合的操作,例如索引/集合删除和创建。
下表列出了一些操作以及它们用于文档级锁定存储引擎的锁定类型:
操作 | 数据库 | 集合级别锁 |
---|---|---|
发出查询 | r (意向共享) | r (意向共享) |
插入资料 | w (意向排他) | w (意向排他) |
删除资料 | w (意向排他) | w (意向排他) |
更新数据 | w (意向排他) | w (意向排他) |
执行聚合操作 | r (意向共享) | r (意向共享) |
创建索引(前台) | W (排他) | |
创建索引(后台) | w (意向排他) | w (意向排他) |
列出集合列表 | r (意向共享)在版本4.0中更改。 | |
映射减少操作 | W (排他)和R (共享) | w (意向排他)和r (意向共享) |
以下管理操作需要在数据库级别上长时间进行排他锁定:
运作方式 | 方法 |
---|---|
| |
| |
| |
| |
_在版本4.2中进行了更改。如果在同一数据库中重命名集合,则该操作将对源集合和目标集合进行排他(W)锁定。在MongoDB 4.2之前的版本中,在同一数据库中重命名时,该操作将对数据库使用排他(W)锁。(仅)如果目标名称空间与源集合位于不同的数据库中,则锁定行为取决于版本: renameCollection (MongoDB 4.2.2和更高版本)在跨数据库重命名集合时,该操作在目标数据库上获得排他(W)锁,并阻塞该数据库上的其他操作,直到操作完成。(MongoDB 4.2.1和更早版本)_在跨数据库重命名集合时,该操作采用全局排他(W)锁,并阻止其他操作,直到操作完成。 |
以下管理操作将锁定数据库,但仅在很短的时间内保持锁定:
运作方式 | 方法 |
---|---|
| |
|
也可以看看
在版本4.2中进行了更改。
以下管理操作需要在集合级别具有排他锁定:
运作方式 | 方法 |
---|---|
| |
| |
| |
| |
_在版本4.2中进行了更改。_如果在同一数据库中重命名集合,则该操作将对源集合和目标集合进行排他(W)锁定。在MongoDB 4.2之前的版本中,在同一数据库中重命名时,该操作将对数据库使用排他(W)锁。(仅)如果目标名称空间与源集合位于不同的数据库中,则锁定行为取决于版本: renameCollection MongoDB 4.2.2及更高版本_在跨数据库重命名集合时,_该操作将对目标数据库进行排他(W)锁定,并阻塞该数据库上的其他操作,直到操作完成。_MongoDB 4.2.1和更早版本_在跨数据库重命名集合时,该操作将使用全局排他(W)锁,并阻止其他操作,直到操作完成。 | |
_在版本4.2中进行了更改。_对于MongoDB 4.2.2和更高版本,这些操作在集合上获得排他(W)锁,并在集合上阻止其他操作,直到完成。对于MongoDB 4.0.0到4.2.1,这些操作采用全局排他(W)锁定并阻止其他操作,直到完成。 | |
_在版本4.2中进行了更改。_对于MongoDB 4.2.2及更高版本,此操作对 oplog 集合进行排他(W)锁定,并阻止对集合的其他操作,直到完成。对于MongoDB 4.2.1和更早版本,此操作采用全局排他(W)锁定并阻止其他操作,直到完成。 |
在MongoDB 4.2之前的版本,以上命令操作了对数据库的排他锁,阻止所有数据库操作_和_它的汇集,直到操作完成。
以下MongoDB操 作可能会在多个数据库上获得并持有锁:
运作方式 | 方法 |
---|---|
此操作获得全局(W)排他锁,并阻止其他操作,直到完成为止。 | |
_在版本4.2中进行了更改。_对于MongoDB 4.0.0到4.2.1,这些操作采用全局排他(W)锁定并阻止其他操作,直到完成。从MongoDB 4.2.2开始,这些操作仅获得排他(W)集合锁,而不是全局排他 锁。在MongoDB 4.0之前,这些操作获得了排他(W)数据库锁。 | |
_在版本4.2中进行了更改。_对于MongoDB 4.2.1和更早版本,此操作在重命名数据库之间的集合时会获得全局排他(W)锁,并阻止其他操作直到完成。从MongoDB 4.2.2开始,此操作仅在目标数据库上获得互斥(W)锁定,在源数据库上获得意向共享(r)锁定,并在源集合上获得共享(S)锁定,而不是全局排他锁。 | |
_在版本4.2中进行了更改。_对于MongoDB 4.2.1和更早版本,此操作获得全局排他(W)锁并阻止其他操作,直到完成。从MongoDB 4.2.2开始,此操作仅在 oplog 集合上获得排他(W)锁,而不是全局排他锁。 |
从MongoDB 4.0开始,如果从节点正在复制,则读取从数据的WiredTiger快照读取的 目标从节点数据。这允许读取与复制同时进行,同时仍保证数据的一致视图。在MongoDB 4.0之前的版本中,将在所有正在进行的复制完成之前阻止对从节点的读取操作。有关更多信息,请参见多线程复制。
由于单个文档可以包含关联数据(译者注:通过内嵌文档或数组的方式),否则它们将在关系模式中的各个父子表之间建模,因此MongoDB的单文档原子操作已经提供了满足大多数应用程序数据完整性需求的事务语义。可以在单个操作中写入一个或多个字段,包括对多个子文档和数组元素的更新。MongoDB提供的保证可确保在文档更新时完全隔离。任何错误都会导致操作回滚,以使客户端获得一致的文档视图。
但是,对于需要对多个文档(在单个或多个集合中)进行读写原子性的情况,MongoDB支持多文档事务:
- 在版本4.0中,MongoDB支持副本集上的多文档事务。
- 在版本4.2中,MongoDB引入了分布式事务,它增加了对分片群集上多文档事务的支持,并合并了对副本集上多文档事务的现有支持。
重要
在大多数情况下,与单文档写入相比,多文档事务产生的性能成本更高,并且多文档事务的可用性不应代替高效的模式设计。在许多情况下, 非规范化数据模型(嵌入式文档和数组)将继续是您的数据和用例的最佳选择。也就是说,在许多情况下,对数据进行适当的建模将最大程度地减少对多文档事务的需求。
有关信息,请参阅:
译者:钟秋
update:小芒果
最近更新 1yr ago