Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

281 lines (215 sloc) 11.874 kb
================
FAQ: Concurrency
================
.. default-domain:: mongodb
.. versionchanged:: 3.0
MongoDB allows multiple clients to read and write the same data.
In order to ensure consistency, it uses locking and other
:term:`concurrency control` measures to prevent multiple clients
from modifying the same piece of data simultaneously.
Together, these mechanisms guarantee that all writes to a single
document occur either in full or not at all and that clients never
see an inconsistent view of the data.
.. _faq-concurrency-locking:
What type of locking does MongoDB use?
--------------------------------------
MongoDB uses reader-writer locks that allow concurrent readers
shared access to a resource, such as a database or collection, but
give exclusive access to a single write operation.
MongoDB uses multi-granularity locking [#mgl-ref]_ 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 (i.e., at the document-level
in WiredTiger).
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. When locking at a certain granularity
all higher levels are locked using an :term:`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. 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 coexists with intent shared (IS) locks.
.. |rarr| unicode:: 0x2192 .. right arrow
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:
IS |rarr| IS |rarr| X |rarr| X |rarr| S |rarr| IS
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.
.. [#mgl-ref] See the Wikipedia page on `Multiple granularity locking
<http://en.wikipedia.org/wiki/Multiple_granularity_locking>`_ for
more information.
How granular are locks in MongoDB?
----------------------------------
.. versionchanged:: 3.0
Beginning with version 3.0, MongoDB ships with the :ref:`WiredTiger
<storage-wiredtiger>` storage engine, which uses optimistic concurrency
control for most read and write operations. 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.
Some global operations, typically short lived operations involving
multiple databases, still require a global "instance-wide" lock.
Some other operations, such as dropping a collection, still require
an exclusive database lock.
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.
How do I see the status of locks on my :program:`mongod` instances?
-------------------------------------------------------------------
For reporting on lock utilization information on locks, use any of the
following methods:
- :method:`db.serverStatus()`,
- :method:`db.currentOp()`,
- :doc:`mongotop </reference/program/mongotop>`,
- :doc:`mongostat </reference/program/mongostat>`, and/or
- the :mms-home:`MongoDB Management Service (MMS) </>`
Specifically, the :data:`~serverStatus.locks` document in the :doc:`output of
serverStatus </reference/command/serverStatus>`, or the :data:`~currentOp.locks` field
in the :doc:`current operation reporting </reference/method/db.currentOp>`
provides insight into the type of locks and amount of lock
contention in your :program:`mongod` instance.
To terminate an operation, use :method:`db.killOp()`.
.. _faq-concurrency-yielding:
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 under many conditions. MongoDB operations can
also yield locks between individual document modifications in write
operations that affect multiple documents like
:method:`~db.collection.update()` with the ``multi`` parameter.
MongoDB's :ref:`mmapv1 <storage-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 :term:`concurrency
control`, yielding is not necessary when accessing storage, as the
:term:`intent locks <intent lock>` held at the global, database and
collection level do not block other readers and writers.
.. versionchanged:: 2.6
MongoDB does not yield locks when scanning an index even if it
predicts that the index is not in memory.
.. _faq-concurrency-operations-locks:
Which operations lock the database?
-----------------------------------
.. versionchanged:: 2.2
The following table lists common database operations and the types of
locks they use.
.. todo In the table below (in the include), the issue of blocked
JavaScript might no longer apply in version 2.4, which will use V8.
.. include:: /includes/table/lock-behavior-per-operation.rst
Which administrative commands lock the database?
------------------------------------------------
Certain administrative commands can exclusively lock the database for
extended periods of time. In some deployments, for large databases,
you may consider taking the :program:`mongod` instance offline so that
clients are not affected. For example, if a :program:`mongod` is part
of a :term:`replica set`, take the :program:`mongod` offline and let
other members of the set service load while maintenance is in progress.
The following administrative operations require an exclusive
(i.e. write) lock on the database for extended periods:
- :method:`db.collection.createIndex()`, when issued
*without* setting ``background`` to ``true``,
- :dbcommand:`reIndex`,
- :dbcommand:`compact`,
- :method:`db.repairDatabase()`,
- :method:`db.createCollection()`, when creating a very large
(i.e. many gigabytes) capped collection,
- :method:`db.collection.validate()`, and
- :method:`db.copyDatabase()`. This operation may lock all
databases. See :ref:`faq-concurrency-lock-multiple-dbs`.
The following administrative commands lock the database but only hold
the lock for a very short time:
- :method:`db.collection.dropIndex()`,
- :method:`db.getLastError()`,
- :method:`db.isMaster()`,
- :method:`rs.status()` (i.e. :dbcommand:`replSetGetStatus`),
- :method:`db.serverStatus()`,
- :method:`db.auth()`, and
- :method:`db.addUser()`.
.. _faq-concurrency-lock-multiple-dbs:
Does a MongoDB operation ever lock more than one database?
----------------------------------------------------------
The following MongoDB operations lock multiple databases:
- :method:`db.copyDatabase()` must lock the entire :program:`mongod`
instance at once.
- :method:`db.repairDatabase()` obtains a global write lock and will block
other operations until it finishes.
- :term:`Journaling <journal>`, which is an internal operation, locks
all databases for short intervals. All databases share a single
journal.
- :doc:`User authentication </core/authentication>` requires a read
lock on the ``admin`` database for deployments using :ref:`2.6 user
credentials <admin-system-users-collection>`. For deployments using
the 2.4 schema for user credentials, authentication locks the
``admin`` database as well as the database the user is accessing.
- All writes to a replica set's :term:`primary` lock both the database
receiving the writes and then the ``local`` database for a short
time. The lock for the ``local`` database allows the
:program:`mongod` to write to the primary's :term:`oplog` and
accounts for a small portion of the total time of the operation.
How does sharding affect concurrency?
-------------------------------------
:term:`Sharding <sharding>` improves concurrency by distributing
collections over multiple :program:`mongod` instances, allowing shard
servers (i.e. :program:`mongos` processes) to perform any number of
operations concurrently to the various downstream :program:`mongod`
instances.
Each :program:`mongod` instance is independent of the others in the
shard cluster and uses its own :ref:`locks
<faq-concurrency-locking>`. The operations on one :program:`mongod`
instance do not block the operations on any others.
.. _faq-concurrency-replication:
How does concurrency affect a replica set primary?
--------------------------------------------------
In :term:`replication`, when MongoDB writes to a collection on the
:term:`primary`, MongoDB also writes to the primary's :term:`oplog`,
which is a special collection in the ``local`` database. Therefore,
MongoDB must lock both the collection's database and the ``local``
database. The :program:`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.
How does concurrency affect secondaries?
----------------------------------------
In :term:`replication`, MongoDB does not apply writes serially to
:term:`secondaries <secondary>`. Secondaries collect oplog entries in
batches and then apply those batches in parallel. Secondaries do not
allow reads while applying the write operations, and apply write
operations in the order that they appear in the oplog.
MongoDB can apply several writes in parallel on replica set
secondaries, in two phases:
1. During the first *prefer* phase, under a read lock, the
:program:`mongod` ensures that all documents affected by the
operations are in memory. During this phase, other clients may
execute queries against this member.
2. A thread pool using write locks applies all write operations in the
batch as part of a coordinated write phase.
What kind of concurrency does MongoDB provide for JavaScript operations?
------------------------------------------------------------------------
.. versionchanged:: 2.4
The V8 JavaScript engine added in 2.4 allows multiple JavaScript
operations to run at the same time. Prior to 2.4, a single
:program:`mongod` could only run a *single* JavaScript operation at
once.
Jump to Line
Something went wrong with that request. Please try again.