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

On this page本页内容

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)时,相应的数据库锁和全局锁都必须在意图排他(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.表示共享锁。
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.表示共享锁。
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. 对于支持文档级并发控制的存储引擎,例如WiredTiger,在访问存储时不需要让步,因为全局、数据库和集合级别的意图锁不会阻止其他读写器。However, operations will periodically yield, such as:然而,操作将定期产生收益,例如:

  • 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:此外,根据MongoDB的版本,renameCollection命令和相应的db.collection.renameCollection() shell方法会使用以下锁:

Command命令MongoDB 4.2.2 or later及以上版本MongoDB 4.2.0 - 4.2.1MongoDB 4.0.X and previousMongoDB 4.0X及以上版本
renameCollection database command数据库命令

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 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 methodshell助手方法If 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 methodsshell方法
  • createIndexes command and corresponding 命令及相应的db.collection.createIndex() and db.collection.createIndexes() shell methodsshell方法
  • drop command and corresponding 命令及相应的db.collection.drop() shell methodsshell方法
  • dropIndexes command and corresponding 命令及相应的db.collection.dropIndex() and db.collection.dropIndexes() shell methodsshell方法
  • the renameCollection command and corresponding 命令及相应的db.collection.renameCollection() shell method take the following locks, depending on version: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. 对于renameCollectiondb.collection.renameCollection():如果重命名同一数据库中的集合,该操作将对源集合和目标集合进行独占(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:仅适用于renameCollection:如果目标命名空间与源集合位于不同的数据库中,则锁定行为取决于版本:

      • 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行为
db.copyDatabase()This operation obtains a global (W) exclusive lock and blocks other operations until it finishes.此操作获得全局(W)独占锁,并阻止其他操作,直到完成。
reIndex
db.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)数据库锁。

renameCollection

Changed 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)锁,而不是全局独占锁。

replSetResizeOplog

Changed 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还会写入主服务器的oplog,这是本地数据库中的一个特殊集合。Therefore, MongoDB must lock both the collection's database and the local database. 因此,MongoDB必须同时锁定集合的数据库和local数据库。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.写入副本集时,锁的作用域将应用于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. 二级数据库分批集合oplog条目,然后并行应用这些批。Writes are applied in the order that they appear in the oplog.写入将按照它们在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.在版本4.0中,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.在版本4.2中,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.有关其他事务使用注意事项(如运行时限制和oplog大小限制),请参阅生产注意事项

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持有一个意向排它(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:有关信息,请参阅:

←  FAQ: IndexesFAQ: Sharding with MongoDB →