翻译或纠错本页面

FAQ: 并发

在 3.0 版更改.

MongoDB 通过使用系统锁,允许多个客户端同时读写单独的数据库,并且确保所有的客户端得到同样的数据视图,防止多个应用同时修改同一块数据的确切位置,锁机制帮助确保单一文档的所有写操作完全发生或不发生。

What type of locking does MongoDB use?

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 uses reader-writer locks that allow concurrent readers shared access to a resource, such as a database or collection, but in MMAPv1, give exclusive access to a single write operation.

MongoDB 使用一个readers-writer [#multi-reader-lock-names]_ 锁,它允许并发多个读操作访问数据库,但是只提供唯一写操作访问。

当一个读操作锁存在时,许多读操作可以使用这个锁。然而,当一个写操作存在时,一个写操作会排他性的保持这个锁,并且不能有其他的读操作或者写操作可以共享这个锁。

Locks are fair, with reads and writes being queued in order. However, to optimize throughput, when one request is granted, all other compatible requests will be granted at the same time, potentially releasing them before a conflicting request. For example, consider a case in which an X lock was just released, and in which the conflict queue contains the following items:

锁是”写贪婪,” 这意味着写操作锁比读操作具有优先权,当写操作和读操作同时等待一个锁,MongoDB会授予读操作这个锁。

In strict first-in, first-out (FIFO) ordering, only the first two IS modes would be granted. 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. As a grant will always move all other requests ahead in the queue, no starvation of any request is possible.

[1]

你可能很熟悉”readers-writer”锁, “multi-reader”锁或”shared exclusive” 锁。参见 Wikipedia 页 Readers-Writer 锁 获得更多 信息。

MongoDB中锁的颗粒度是什么?

在 3.0 版更改.

For WiredTiger

Beginning with version 3.0, MongoDB ships with the WiredTiger storage engine.

For most read and write operations, WiredTiger uses optimistic concurrency control. WiredTiger uses only intent locks at the global, database and collection levels. When the storage engine detects conflicts between two operations, one will incur a write conflict causing MongoDB to transparently retry that operation.

举个例子,如果你有六个数据库和一个数据库级别的写锁,其他的五个数据库的读写依然有效。一个全局锁在操作期间会使所有的六个数据库都不可用。

For MMAPv1

The MMAPv1 storage engine uses collection-level locking as of the 3.0 release series, an improvement on earlier versions in which the database lock was the finest-grain lock. Third-party storage engines may either use collection-level locking or implement their own finer-grained concurrency control.

For example, if you have six collections in a database using the MMAPv1 storage engine and an operation takes a collection-level write lock, the other five collections are still available for read and write operations. An exclusive database lock makes all six collections unavailable for the duration of the operation holding the lock.

在我的 mongod 实例中如何看到锁的状态?

要获得锁使用信息的报告,使用下列方法:

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.

终止一个操作,使用 db.killOp().

一个读操作或写操作产生锁吗?

在某些情况下,读操作和写操作产生自己的锁。

长期运行的读操作和写操作,比如查询,更新,删除,在很多情况下会产生锁。MongoDB 基于可预测磁盘访问模式使用一个自适应算法允许操作产生锁。(比如:页面错误。)

MongoDB’s MMAPv1 storage engine uses heuristics based on its access pattern to predict whether data is likely in physical memory before performing a read. If MongoDB predicts that the data is not in physical memory, an operation will yield its lock while MongoDB loads the data into memory. Once data is available in memory, the operation will reacquire the lock to complete the operation.

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.

在 2.6 版更改: MongoDB 从扫描一个索引一直到预测出这个索引不在内存中的时候不会产生锁。

哪些操作会锁住数据库?

下表列出了常用的数据库操作和他们使用锁的类型。

操作

锁类型

查询操作

读锁

从一个 cursor 中获得更多数据

读锁

插入数据

写锁

删除数据

写锁

更新数据

写锁

Map-reduce

读锁和写锁,除非被指定为非原子性操作。部分 map-reduce 的工作可以同时运行。

创建一个索引

在前台创建一个索引,这是默认的,会长时间的锁定数据库。

db.eval()

3.0 版后已移除.

写锁, db.eval() 方法在评估JavaScript函数的时候使用了一个全局写锁,你可以使用 eval 命令,带上 nolock: true

eval

3.0 版后已移除.

写锁。默认的, eval 命令在评估JavaScript函数的时候使用一个全局写锁。如果使用参数 nolock: trueeval 命令在评估JavaScript函数的时候不会使用全局写锁。然而,JavaScript函数可能为写操作接收一个写锁。

aggregate()

读锁

哪些管理命令会锁定数据库?

某些管理命令会长时间排他性的锁定数据库。在一些部署中,对于大的数据库,你可能会考虑让 mongod 实例脱机,这样客户端不会受影响。比如:如果 mongod 是一个 复制集 的一部分,让:program:mongod 脱机让集群中的其他成员来负载,当维护进行中的时候。

下列的管理命令会在数据库上申请一个排他性的(比如:写操作)锁很长时间。

下列的管理操作会锁住数据库,但是只保持锁非常短的时间:

MongoDB 操作是否会锁多个数据库?

下列MongoDB 操作会锁多个数据库:

  • db.copyDatabase() 必须一次锁住整个 mongod 实例。

  • db.repairDatabase() 获得一个全局写锁,将阻止其他的操作,直到完成。

  • Journaling ,这是一个内部操作,在很短的时间内锁住所有的数据库,所有的数据库共享一个日志。

  • User authentication 请求一个读锁在 admin 数据库中, 部署使用 2.6 user credentials。 使用 2.4 模式来部署用户凭证,验证锁住 admin 数据库,以及用户访问数据库。

  • 所有对复制集的写操作 primary 会锁住数据库接收写操作和 local 数据库很短的时间。local 数据库的锁允许 mongod 写入主节点的 oplog ,这占用整个操作总时间的很小的部分。

分片如何影响并发?

Sharding 通过分布数据集在多个 mongod 实例上来改善并发,允许分片服务器 (比如:program: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 shard cluster and uses its own locks. The operations on one mongod instance do not block the operations on any others.

并发如何影响复制集中的主节点?

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. Therefore, MongoDB must lock both the collection’s database and the local database. 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.

When writing to a replica set, the lock’s scope applies to the primary.

并发如何影响从节点?

复制集 中, MongoDB 不会连续的申请写操作到:term:子节点 <secondary>。子节点批量的收集 oplog 记录,然后并行的申请。字节点在申请这个写操作的时候不允许读操作,并根据他们出现在oplog中的顺序应用这些写操作。

Does MongoDB support transactions?

MongoDB does not support multi-document transactions.

However, MongoDB does provide atomic operations on a single document. Often these document-level atomic operations are sufficient to solve problems that would require ACID transactions in a relational database.

For example, in MongoDB, you can embed related data in nested arrays or nested documents within a single document and update the entire document in a single atomic operation. Relational databases might represent the same kind of data with multiple tables and rows, which would require transaction support to update the data atomically.

What isolation guarantees does MongoDB provide?

MongoDB provides the following guarantees in the presence of concurrent read and write operations. These guarantees hold on systems configured with either the MMAPv1 or WiredTiger storage engines.

  1. Write operations are atomic with respect to a single document; i.e. if a write is updating multiple fields in the document, a reader will never see the document with only some of the fields updated.

    With a standalone mongod instance, a set of read and write operations to a single document is serializable. With a replica set, a set of read and write operations to a single document is serializable only in the absence of a rollback.

  2. Correctness with respect to query predicates, e.g. db.collection.find() will only return documents that match and db.collection.update() will only write to matching documents.

  3. Correctness with respect to sort. For read operations that request a sort order (e.g. db.collection.find() or db.collection.aggregate()), the sort order will not be violated due to concurrent writes.

Although MongoDB provides these strong guarantees for single-document operations, read and write operations may access an arbitrary number of documents during execution. Multi-document operations do not occur transactionally and are not isolated from concurrent writes. This means that the following behaviors are expected under the normal operation of the system, for both the MMAPv1 and WiredTiger storage engines:

  1. Non-point-in-time read operations. Suppose a read operation begins at time t1 and starts reading documents. A write operation then commits an update to one of the documents at some later time t2. The reader may see the updated version of the document, and therefore does not see a point-in-time snapshot of the data.
  2. Non-serializable operations. Suppose a read operation reads a document d1 at time t1 and a write operation updates d1 at some later time t3. This introduces a read-write dependency such that, if the operations were to be serialized, the read operation must precede the write operation. But also suppose that the write operation updates document d2 at time t2 and the read operation subsequently reads d2 at some later time t4. This introduces a write-read dependency which would instead require the read operation to come after the write operation in a serializable schedule. There is a dependency cycle which makes serializability impossible.
  3. Reads may miss matching documents that are updated during the course of the read operation.

Can reads see changes that have not been committed to disk?

在 3.2 版更改: MongoDB 3.2 introduces readConcern option. Clients using majority readConcern cannot see the results of writes before they are made durable.

Readers, using "local" readConcern can see the results of writes before they are made durable, regardless of write concern level or journaling configuration. As a result, applications may observe the following behaviors:

  1. MongoDB will allow a concurrent reader to see the result of the write operation before the write is acknowledged to the client application. For details on when writes are acknowledged for different write concern levels, see Write Concern.
  2. Reads can see data which may subsequently be rolled back in cases such as replica set failover or power loss. It does not mean that read operations can see documents in a partially written or otherwise inconsistent state.

Other systems refer to these semantics as read uncommitted.

在 3.2 版更改.