Docs HomeMongoDB Manual

FAQ: Concurrency常见问题解答:并发

MongoDB allows multiple clients to read and write the same data. MongoDB允许多个客户端读取和写入相同的数据。To ensure consistency, MongoDB uses locking and concurrency control to prevent clients from modifying the same data simultaneously. 为了确保一致性,MongoDB使用锁定和并发控制来防止客户端同时修改相同的数据。Writes to a single document occur either in full or not at all, and clients always see consistent data.

What type of locking does MongoDB use?MongoDB使用什么类型的锁定?

MongoDB uses multi-granularity locking [1] that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).MongoDB使用多粒度锁定[1],允许操作在全局、数据库或集合级别锁定,并允许单个存储引擎在集合级别以下实现自己的并发控制(例如,在WiredTiger中的文档级别)。

MongoDB uses reader-writer locks that allow concurrent readers shared access to a resource, such as a database or collection.MongoDB使用读写器锁,允许并发读写器共享访问资源,如数据库或集合。

In addition to a shared (S) locking mode for reads and an exclusive (X) locking mode for write operations, intent shared (IS) and intent exclusive (IX) modes indicate an intent to read or write a resource using a finer granularity lock. 除了用于读取的共享(S)锁定模式和用于写入操作的排他(X)锁定模式之外,意图共享(IS)和意图排他(IX)模式指示使用更细粒度锁定来读取或写入资源的意图。When locking at a certain granularity, all higher levels are locked using an intent lock.当以特定粒度进行锁定时,所有更高级别都使用意向锁进行锁定。

For example, when locking a collection for writing (using mode X), both the corresponding database lock and the global lock must be locked in intent exclusive (IX) mode. 例如,当锁定集合以进行写入(使用模式X)时,相应的数据库锁和全局锁都必须以intent exclusive(IX)模式锁定。A single database can simultaneously be locked in IS and IX mode, but an exclusive (X) lock cannot coexist with any other modes, and a shared (S) lock can only coexist with intent shared (IS) locks.单个数据库可以在IS和IX模式下同时锁定,但独占(X)锁不能与任何其他模式共存,共享(S)锁只能与意向共享(IS)锁共存。

Locks are fair, with lock requests for reads and writes queued in order. However, to optimize throughput, when one lock request is granted, all other compatible lock requests are granted at the same time, potentially releasing the locks before a conflicting lock request is performed. 锁是公平的,读写的锁请求按顺序排队。然而,为了优化吞吐量,当一个锁请求被授予时,所有其他兼容的锁请求都会同时被授予,这可能会在执行冲突的锁请求之前释放锁。For example, consider a situation where an X lock was just released and the conflict queue contains these locks:例如,考虑一种情况,其中X锁刚刚被释放,而冲突队列包含这些锁:

IS → IS → X → X → S → IS

In strict first-in, first-out (FIFO) ordering, only the first two IS modes would be granted. 在严格的先进先出(FIFO)排序中,只允许前两种IS模式。Instead MongoDB will actually grant all IS and S modes, and once they all drain, it will grant X, even if new IS or S requests have been queued in the meantime. 相反,MongoDB实际上会授予所有IS和S模式,一旦它们全部耗尽,它就会授予X,即使在此期间新的IS或S请求已经排队。As a grant will always move all other requests ahead in the queue, no starvation of any request is possible.由于授权总是将队列中的所有其他请求移到前面,因此不可能出现任何请求的饥饿。

In db.serverStatus() and db.currentOp() output, the lock modes are represented as follows:db.serverStatus()db.currentOp()输出中,锁模式表示如下:

Lock Mode锁定模式Description描述
RRepresents Shared (S) lock.表示共享(S)锁。
WRepresents Exclusive (X) lock.表示独占(X)锁。
rRepresents Intent Shared (IS) lock.表示意向共享(IS)锁。
wRepresents Intent Exclusive (IX) lock.表示意向独占(IX)锁。
[1] See the Wikipedia page on Multiple granularity locking for more information.有关更多信息,请参阅维基百科的多粒度锁定页面。

How granular are locks in MongoDB?MongoDB中的锁有多细粒度?

For most read and write operations, WiredTiger uses optimistic concurrency control. 对于大多数读写操作,WiredTiger使用乐观并发控制。WiredTiger uses only intent locks at the global, database and collection levels. WiredTiger仅在全局、数据库和集合级别使用意向锁。When the storage engine detects conflicts between two operations, one will incur a write conflict causing MongoDB to transparently retry that operation.当存储引擎检测到两个操作之间的冲突时,其中一个操作将引发写冲突,导致MongoDB透明地重试该操作。

Some global operations, typically short lived operations involving multiple databases, still require a global "instance-wide" lock. 一些全局操作,通常是涉及多个数据库的短期操作,仍然需要全局“实例范围”锁定。Some other operations, such as collMod, still require an exclusive database lock.其他一些操作,如collMod,仍然需要独占数据库锁。

How do I see the status of locks on my mongod instances?如何查看mongod实例上锁的状态?

For reporting on lock utilization information on locks, use any of these methods:要报告锁的锁利用率信息,请使用以下任意方法:

Specifically, the locks document in the output of serverStatus, or the locks field in the current operation reporting provides insight into the type of locks and amount of lock contention in your mongod instance.具体地说,serverStatus输出中的locks文档或当前操作报告中的locks字段可以深入了解mongod实例中的锁类型和锁争用量。

In db.serverStatus() and db.currentOp() output, the lock modes are represented as follows:db.serverStatus()db.currentOp()输出中,锁模式表示如下:

Lock Mode锁定模式Description描述
RRepresents Shared (S) lock.表示共享(S)锁。
WRepresents Exclusive (X) lock.表示独占(X)锁。
rRepresents Intent Shared (IS) lock.表示意向共享(IS)锁。
wRepresents Intent Exclusive (IX) lock.表示意向独占(IX)锁。

To terminate an operation, use db.killOp().要终止操作,请使用db.killOp()

Does a read or write operation ever yield the lock?读或写操作是否会产生锁?

In some situations, read and write operations can yield their locks.在某些情况下,读和写操作可能会产生锁。

Long running read and write operations, such as queries, updates, and deletes, yield locks under many conditions. 长时间运行的读写操作,如查询、更新和删除,在许多情况下都会产生锁。MongoDB operations can also yield locks between individual document modifications in write operations that affect multiple documents.MongoDB操作还可以在影响多个文档的写入操作中的单个文档修改之间产生锁。

For storage engines supporting document level concurrency control, such as WiredTiger, yielding is not necessary when accessing storage as the intent locks, held at the global, database and collection level, do not block other readers and writers. However, operations will periodically yield, such as:对于支持文档级并发控制的存储引擎(如WiredTiger),访问存储时不需要让步,因为全局、数据库和集合级别的意向锁不会阻止其他读写器。但是,操作会周期性地产生收益,例如:

  • to avoid long-lived storage transactions because these can potentially require holding a large amount of data in memory;避免长期存储事务,因为这些事务可能需要在内存中保存大量数据;
  • to serve as interruption points so that you can kill long running operations;充当中断点,这样就可以终止长时间运行的操作;
  • to allow operations that require exclusive access to a collection such as index/collection drops and creations.以允许需要对集合进行独占访问的操作,例如索引/集合删除和创建。

What locks are taken by some common client operations?一些常见的客户端操作使用哪些锁?

The following table lists some operations and the types of locks they use for document level locking storage engines:下表列出了一些操作以及它们用于文档级锁定存储引擎的锁类型:

Operation操作Database数据库Collection集合
Issue a query发出查询r (Intent Shared)(意向共享)r (Intent Shared)(意向共享)
Insert data插入数据w (Intent Exclusive)(意向专用)w (Intent Exclusive)(意向专用)
Remove data删除数据w (Intent Exclusive)(意向专用)w (Intent Exclusive)(意向专用)
Update data更新数据w (Intent Exclusive)(意向专用)w (Intent Exclusive)(意向专用)
Perform Aggregation执行聚合r (Intent Shared)(意向共享)r (Intent Shared)(意向共享)
Create an index (Foreground)创建索引(前景)W (Exclusive)(独家)
Create an index (Background)创建索引(背景)w (Intent Exclusive)(意向专用)w (Intent Exclusive)(意向专用)
List collections列出集合r (Intent Shared)(意向共享)
Changed in version 4.0.在4.0版中进行了更改。
Map-reduceW (Exclusive) and R (Shared)w (Intent Exclusive) and (意向专用)和r (Intent Shared)(意向共享)

Which administrative commands lock a database?哪些管理命令锁定数据库?

Some administrative commands can exclusively lock a database for extended time periods. 某些管理命令可以在较长的时间段内以独占方式锁定数据库。For large database deployments, you may consider taking the mongod instance offline so that clients are not affected. 对于大型数据库部署,您可以考虑将mongod实例脱机,这样客户端就不会受到影响。For example, if a mongod is part of a replica set, take the mongod offline and let other members of the replica set process requests while maintenance is performed.例如,如果mongod副本集的一部分,请使mongod脱机,并让副本集的其他成员在执行维护时处理请求。

Administrative Commands Taking Extended Locks使用扩展锁的管理命令

These administrative operations require an exclusive lock at the database level for extended periods:这些管理操作需要在数据库级别进行长时间的独占锁定:

In addition, the renameCollection command and corresponding db.collection.renameCollection() shell method take the following locks depending on the version of MongoDB:此外,renameCollection命令和相应的db.collection.renameCollection()shell方法根据MongoDB的版本采用以下锁:

Command命令MongoDB 4.2.2 or laterMongoDB 4.2.0 - 4.2.1MongoDB 4.0.X and previousMongoDB 4.0X及以前版本
renameCollection database commandIf renaming a collection within the same database, the renameCollection command takes an exclusive (W) lock on the source and target collections.如果重命名同一数据库中的集合,renameCollection命令将对源集合和目标集合使用独占(W)锁。
If the target namespace is in a different database as the source collection, The renameCollection command takes an exclusive (W) lock on the target database when renaming a collection across databases and blocks other operations on that database until it finishes.如果目标命名空间与源集合位于不同的数据库中,则在跨数据库重命名集合时,renameCollection命令会对目标数据库执行独占(W)锁,并阻止对该数据库的其他操作,直到操作完成。
If renaming a collection within the same database, the renameCollection command takes an exclusive (W) lock on the source and target collections.如果重命名同一数据库中的集合,renameCollection命令将对源集合和目标集合使用独占(W)锁。
If the target namespace is in a different database as the source collection, The renameCollection command takes a global exclusive (W) lock when renaming a collection across databases and blocks other operations until it finishes.如果目标命名空间与源集合位于不同的数据库中,则在跨数据库重命名集合时,renameCollection命令将使用全局独占(W)锁,并阻止其他操作,直到完成为止。
Prior to MongoDB 4.2, the renameCollection command takes an exclusive (W) lock on the database when renaming within the same database.在MongoDB 4.2之前,renameCollection命令在同一数据库中重命名时会对数据库执行独占(W)锁定。
renameCollection() shell helper methodIf renaming a collection within the same database, the renameCollection() method takes an exclusive (W) lock on the source and target collections.如果重命名同一数据库中的集合,renameCollection()方法将对源集合和目标集合使用独占(W)锁。(same behavior as MongoDB 4.2.2 or later)(行为与MongoDB 4.2.2或更高版本相同)Prior to MongoDB 4.2, the renameCollection() method takes an exclusive (W) lock on the database when renaming within the same database.在MongoDB 4.2之前,renameCollection()方法在同一数据库中重命名时会对数据库执行独占(W)锁。

Administrative Commands Taking Brief Locks使用简短锁定的管理命令

These administrative operations lock a database but only hold the lock for a very short time:这些管理操作锁定数据库,但只在很短的时间内保持锁定:

Which administrative commands lock a collection?哪些管理命令锁定集合?

Changed in version 4.2.4.2版更改。

These administrative operations require an exclusive lock at the collection level:这些管理操作需要在集合级别使用独占锁定:

  • create command and corresponding db.createCollection() and db.createView() shell methodscreate命令和相应的db.createCollection()db.createView()shell方法
  • createIndexes command and corresponding db.collection.createIndex() and db.collection.createIndexes() shell methods命令和相应的db.collection.createIndex()db.collection.createIndexes()shell方法
  • drop command and corresponding db.collection.drop() shell methodsdrop命令和相应的db.collection.drop()shell方法
  • dropIndexes command and corresponding db.collection.dropIndex() and db.collection.dropIndexes() shell methodsdropIndexes命令以及相应的db.collection.dropIndex()db.collection.dropIndexes()shell方法
  • the renameCollection command and corresponding db.collection.renameCollection() shell method take the following locks, depending on version:renameCollection命令和相应的db.collection.renameCollection()shell方法根据版本采用以下锁:

    • For 对于renameCollection and db.collection.renameCollection(): If renaming a collection within the same database, the operation takes an exclusive (W) lock on the source and target collections. :如果重命名同一数据库中的集合,则该操作将对源集合和目标集合使用独占(W)锁。Prior to MongoDB 4.2, the operation takes an exclusive (W) lock on the database when renaming within the same database.在MongoDB 4.2之前,当在同一数据库中重命名时,该操作会对数据库进行独占(W)锁定。
    • For renameCollection only: If the target namespace is in a different database as the source collection, the locking behavior is version dependent::如果目标命名空间与源集合位于不同的数据库中,则锁定行为取决于版本:

      • MongoDB 4.2.2 and later The operation takes an exclusive (W) lock on the target database when renaming a collection across databases and blocks other operations on that database until it finishes.MongoDB 4.2.2及更高版本当跨数据库重命名集合时,该操作对目标数据库执行独占(W)锁定,并阻止该数据库上的其他操作,直到操作完成。
      • MongoDB 4.2.1 and earlier The operation takes a global exclusive (W) lock when renaming a collection across databases and blocks other operations until it finishes.MongoDB 4.2.1及更早版本该操作在跨数据库重命名集合时使用全局独占(W)锁,并阻止其他操作直到完成。
  • the reIndex command and corresponding db.collection.reIndex() shell method take the following locks, depending on version:reIndex命令和相应的db.collection.reIndex()shell方法根据版本采用以下锁:

    • For MongoDB 4.2.2 and later, these operations obtain an exclusive (W) lock on the collection and block other operations on the collection until finished.对于MongoDB 4.2.2及更高版本,这些操作获得了对集合的独占(W)锁,并阻止对集合的其他操作,直到完成为止。
    • For MongoDB 4.0.0 through 4.2.1, these operations take a global exclusive (W) lock and block other operations until finished.对于MongoDB 4.0.0到4.2.1,这些操作采用全局独占(W)锁并阻止其他操作直到完成。
  • the replSetResizeOplog command takes the following locks, depending on version:replSetResizeOplog命令根据版本采用以下锁:

    • For MongoDB 4.2.2 and later, this operation takes an exclusive (W) lock on the oplog collection and blocks other operations on the collection until it finishes.对于MongoDB 4.2.2及更高版本,此操作对oplog集合进行独占(W)锁定,并阻止该集合上的其他操作,直到完成为止。
    • For MongoDB 4.2.1 and earlier, this operation takes a global exclusive (W) lock and blocks other operations until it finishes.对于MongoDB 4.2.1及更早版本,此操作采用全局独占(W)锁并阻止其他操作,直到完成为止。

Prior to MongoDB 4.2, these operations took an exclusive lock on the database, blocking all operations on the database and its collections until the operation completed.在MongoDB 4.2之前,这些操作对数据库进行独占锁定,阻止对数据库及其集合的所有操作,直到操作完成。

Does a MongoDB operation ever lock more than one database?MongoDB操作是否锁定过多个数据库?

These MongoDB operations may obtain and hold a lock on more than one database:这些MongoDB操作可能会获得并锁定多个数据库:

Operation操作Behavior行为
reIndexdb.collection.reIndex()Changed in version 4.2.在版本4.2中进行了更改。 For MongoDB 4.0.0 through 4.2.1, these operations take a global exclusive (W) lock and block other operations until finished.对于MongoDB 4.0.0到4.2.1,这些操作采用全局独占(W)锁并阻止其他操作直到完成。
Starting in MongoDB 4.2.2, these operations only obtain an exclusive (W) collection lock instead of a global exclusive lock.从MongoDB 4.2.2开始,这些操作只获得一个独占(W)集合锁,而不是全局独占锁。
Prior to MongoDB 4.0, these operations obtained an exclusive (W) database lock.在MongoDB 4.0之前,这些操作获得了独占(W)数据库锁。
renameCollectionChanged in version 4.2.4.2版更改。
For MongoDB 4.2.1 and earlier, this operation obtains a global exclusive (W) lock when renaming a collection between databases and blocks other operations until finished.对于MongoDB 4.2.1及更早版本,此操作在重命名数据库之间的集合时获得全局独占(W)锁,并阻止其他操作直到完成。
Starting in MongoDB 4.2.2, this operation only obtains an exclusive (W) lock on the target database, an intent shared (r) lock on the source database, and a shared (S) lock on the source collection instead of a global exclusive lock. 从MongoDB 4.2.2开始,此操作只获得目标数据库上的独占(W)锁、源数据库上的意向共享(r)锁和源集合上的共享(S)锁,而不是全局独占锁。
replSetResizeOplogChanged in version 4.2.4.2版更改。
For MongoDB 4.2.1 and earlier, this operation obtains a global exclusive (W) lock and blocks other operations until finished.对于MongoDB 4.2.1及更早版本,此操作获得全局独占(W)锁,并阻止其他操作直到完成。
Starting in MongoDB 4.2.2, this operation only obtains an exclusive (W) lock on the oplog collection instead of a global exclusive lock. 从MongoDB 4.2.2开始,此操作只获得oplog集合上的独占(W)锁,而不是全局独占锁。

How does sharding affect concurrency?分片如何影响并发性?

Sharding improves concurrency by distributing collections over multiple mongod instances, allowing shard servers (specifically, mongos processes) to run concurrently with the downstream mongod instances.分片通过在多个mongod实例上分发集合来提高并发性,允许分片服务器(特别是mongos进程)与下游mongod示例并行运行。

In a sharded cluster, locks apply to each individual shard, not to the whole cluster; i.e. each mongod instance is independent of the others in the sharded cluster and uses its own locks. 在分片集群中,锁应用于每个单独的分片,而不是整个集群;即,每个mongod实例都独立于分片集群中的其他实例,并使用自己的The operations on one mongod instance do not block the operations on any others.对一个mongod实例的操作不会阻止对任何其他实例的操作。

How does concurrency affect a replica set primary?并发性如何影响副本集主副本集?

With replica sets, when MongoDB writes to a collection on the primary, MongoDB also writes to the primary's oplog, which is a special collection in the local database. 对于副本集,当MongoDB写入主数据库上的集合时,MongoDB还会写入primaryoplog,这是local数据库中的一个特殊集合。Therefore, MongoDB must lock both the collection's database and the local database. 因此,MongoDB必须锁定集合的数据库和本地数据库。The mongod must lock both databases at the same time to keep the database consistent and ensure that write operations, even with replication, are all or nothing operations.mongod必须同时锁定两个数据库,以保持数据库的一致性,并确保写操作(即使是复制操作)是全有或全无操作。

When writing to a replica set, the lock's scope applies to the primary.当写入副本集时,锁的作用域将应用于副本集。

How does concurrency affect secondaries?并发如何影响辅助设备?

In replication, MongoDB does not apply writes serially to secondaries. 复制中,MongoDB不将串行写入应用于辅助设备。Secondaries collect oplog entries in batches and then apply those batches in parallel. Writes are applied in the order that they appear in the oplog.辅助人员分批集合操作日志条目,然后并行应用这些批处理。写入是按照它们在操作日志中出现的顺序应用的。

Starting in MongoDB 4.0, reads which target secondaries read from a WiredTiger snapshot of the data if the secondary is undergoing replication. 从MongoDB 4.0开始,读取从WiredTiger数据快照读取的目标辅助设备(如果辅助设备正在进行复制)。This allows the read to occur simultaneously with replication, while still guaranteeing a consistent view of the data. Previous to MongoDB 4.0, read operations on secondaries would be blocked until any ongoing replication completes. 这允许读取与复制同时进行,同时仍然保证数据视图的一致性。在MongoDB 4.0之前,在任何正在进行的复制完成之前,都会阻止对辅助设备的读取操作。See Multithreaded Replication for more information.有关详细信息,请参阅多线程复制

Does MongoDB support transactions?MongoDB支持事务吗?

Because a single document can contain related data that would otherwise be modeled across separate parent-child tables in a relational schema, MongoDB's atomic single-document operations already provide transaction semantics that meet the data integrity needs of the majority of applications. 由于单个文档可以包含相关数据,否则这些数据将在关系模式中跨单独的父子表进行建模,因此MongoDB的原子单文档操作已经提供了满足大多数应用程序数据完整性需求的事务语义。One or more fields may be written in a single operation, including updates to multiple sub-documents and elements of an array. 一个或多个字段可以在单个操作中写入,包括对多个子文档和数组元素的更新。The guarantees provided by MongoDB ensure complete isolation as a document is updated; any errors cause the operation to roll back so that clients receive a consistent view of the document.MongoDB提供的保证确保在文档更新时完全隔离;任何错误都会导致操作回滚,以便客户端接收到文档的一致视图。

However, for situations that require atomicity of reads and writes to multiple documents (in a single or multiple collections), MongoDB supports multi-document transactions:然而,对于需要对多个文档(在单个或多个集合中)进行原子性读写的情况,MongoDB支持多文档事务:

  • In version 4.0, MongoDB supports multi-document transactions on replica sets.,MongoDB支持副本集上的多文档事务。
  • In version 4.2, MongoDB introduces distributed transactions, which adds support for multi-document transactions on sharded clusters and incorporates the existing support for multi-document transactions on replica sets.,MongoDB引入了分布式事务,增加了对分片集群上多文档事务的支持,并整合了对副本集上多文档事务的现有支持。

    For details regarding transactions in MongoDB, see the transactions page.有关MongoDB中事务的详细信息,请参阅事务页面。

Important

In most cases, multi-document transaction incurs a greater performance cost over single document writes, and the availability of multi-document transactions should not be a replacement for effective schema design. 在大多数情况下,与单文档写入相比,多文档事务会产生更高的性能成本,并且多文档事务的可用性不应取代有效的模式设计。For many scenarios, the denormalized data model (embedded documents and arrays) will continue to be optimal for your data and use cases. 对于许多场景,非规范化数据模型(嵌入文档和数组)将继续是您的数据和用例的最佳选择。That is, for many scenarios, modeling your data appropriately will minimize the need for multi-document transactions.也就是说,对于许多场景,对数据进行适当建模将最大限度地减少对多文档事务的需求。

For additional transactions usage considerations (such as runtime limit and oplog size limit), see also Production Considerations.有关其他事务使用注意事项(如运行时限制和操作日志大小限制),请参阅生产注意事项

What isolation guarantees does MongoDB provide?MongoDB提供了哪些隔离保证?

Depending on the read concern, clients can see the results of writes before the writes are durable. To control whether the data read may be rolled back or not, clients can use the readConcern option.根据读取关注的不同,客户端可以在写入持久之前看到写入的结果。要控制是否可以回滚读取的数据,客户端可以使用readConcern选项。

What are lock-free read operations?什么是无锁读取操作?

New in version 5.0. 5.0版新增。

A lock-free read operation runs immediately: it is not blocked when another operation has an exclusive (X) write lock on the collection.无锁读取操作会立即运行:当另一个操作对集合具有独占(X)写入锁定时,该操作不会被阻止。

Starting in MongoDB 5.0, the following read operations are not blocked when another operation holds an exclusive (X) write lock on the collection:从MongoDB 5.0开始,当另一个操作对集合持有独占(X)写锁时,以下读取操作不会被阻止:

When writing to a collection, mapReduce and aggregate hold an intent exclusive (IX) lock. 在写入集合时,mapReduceaggregate持有一个intent exclusive(IX)锁。Therefore, if an exclusive X lock is already held on a collection, mapReduce and aggregate write operations are blocked.因此,如果集合上已持有独占X锁,则会阻止mapReduceaggregate写操作。

For information, see:有关信息,请参阅: