Transactions¶
On this page
New in version 4.0.
In MongoDB, an operation on a single document is atomic. Because you can use embedded documents and arrays to capture relationships between data in a single document structure instead of normalizing across multiple documents and collections, this single-document atomicity obviates the need for multi-document transactions for many practical use cases.
However, for situations that require atomicity for updates to multiple documents or consistency between reads to multiple documents:
- Starting in version 4.0, MongoDB provides the ability to perform multi-document transactions against replica sets.
Multi-document transactions can be used across multiple operations, collections, databases, and documents. Multi-document transactions provide an “all-or-nothing” proposition. When a transaction commits, all data changes made in the transaction are saved. If any operation in the transaction fails, the transaction aborts and all data changes made in the transaction are discarded without ever becoming visible. Until a transaction commits, no write operations in the transaction are visible outside the transaction.
Important
In most cases, multi-document transaction incurs a greater performance cost over single document writes, and the availability of multi-document transaction 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.
Transactions API¶
The following mongo
shell example highlights the key
components of using transactions:
Note
The example omits retry logic and robust error handling for simplicity’s sake. For a more practical example of incorporating transactions in applications, see Transactions in Applications instead.
Transactions and Sessions¶
Transactions are associated with a session. That is, you start a transaction for a session. At any given time, you can have at most one open transaction for a session.
Important
When using the drivers, you must pass the session to each operation in the transaction.
If a session ends and it has an open transaction, the transaction aborts.
Transactions and MongoDB Drivers¶
Clients require MongoDB drivers updated for MongoDB 4.0.
Java 3.8.0 Python 3.7.0 C 1.11.0 |
C# 2.7 Node 3.1.0 Ruby 2.6.0 |
Perl 2.0.0 PHP (PHPC) 1.5.0 Scala 2.4.0 |
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction. For examples, see Transactions in Applications.
Transactions and Atomicity¶
Multi-document transactions are atomic:
- When a transaction commits, all data changes made in the transaction are saved and visible outside the transaction. Until a transaction commits, the data changes made in the transaction are not visible outside the transaction.
- When a transaction aborts, all data changes made in the transaction are discarded without ever becoming visible. For example, if any operation in the transaction fails, the transaction aborts and all data changes made in the transaction are discarded without ever becoming visible.
Transactions and Operations¶
For transactions:
- You can specify read/write (CRUD) operations on existing collections. The collections can be in different databases. For a list of CRUD operations, see CRUD Operations.
- You cannot read/write to collections in the
config
,admin
, orlocal
databases. - You cannot write to
system.*
collections. - You cannot return the supported operation’s query plan (i.e.
explain
).
- For cursors created outside of transactions, you cannot call
getMore
inside a transaction. - For cursors created in a transaction, you cannot call
getMore
outside the transaction.
Operations that affect the database catalog, such as creating or dropping a collection or an index, are not allowed in multi-document transactions. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection. See Restricted Operations.
Tip
When creating or dropping a collection immediately before
starting a transaction, if the collection is accessed within the
transaction, issue the create or drop operation with write
concern "majority"
to ensure that the transaction
can acquire the required locks.
Count Operation¶
To perform a count operation within a transaction, use the
$count
aggregation stage or the $group
(with a
$sum
expression) aggregation stage.
MongoDB drivers compatible with the 4.0 features provide a
collection-level API countDocuments(filter, options)
as a helper
method that uses the $group
with a $sum
expression
to perform a count. The 4.0 drivers have deprecated the count()
API.
Starting in MongoDB 4.0.3, the mongo
shell provides the
db.collection.countDocuments()
helper method that uses the
$group
with a $sum
expression to perform a count.
Informational Operations¶
Informational commands, such as hello
,
buildInfo
, connectionStatus
(and their
helper methods) are allowed in transactions; however, they cannot be
the first operation in the transaction.
Restricted Operations¶
The following operations are not allowed in multi-document transactions:
Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.
The
listCollections
andlistIndexes
commands and their helper methods are also excluded.Non-CRUD and non-informational operations, such as
createUser
,getParameter
,count
, etc. and their helpers.
Transactions in Applications¶
Highly Available Applications
Regardless of the database system, whether MongoDB or relational databases, applications should take measures to handle errors during transaction commits and incorporate retry logic for transactions.
Retry Transaction¶
The individual write operations inside the transaction are not
retryable, regardless of whether retryWrites
is set to
true
.
If an operation encounters an error, the returned error may have an
errorLabels
array field. If the error is a transient error, the
errorLabels
array field contains "TransientTransactionError"
as
an element and the transaction as a whole can be retried.
For example, the following helper runs a function and retries the
function if a "TransientTransactionError"
is encountered:
- Mongo Shell
- Python
- Java (Sync)
- Node.js
- PHP
- Other
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Retry Commit Operation¶
The commit operations are retryable write operations. If the commit operation encounters
an error, MongoDB drivers retry the operation a single time regardless
of whether retryWrites
is set to true
.
If the commit operation encounters an error, MongoDB returns an error
with an errorLabels
array field. If the error is a transient commit
error, the errorLabels
array field contains
"UnknownTransactionCommitResult"
as an element and the commit
operation can be retried.
In addition to the single retry behavior provided by the MongoDB
drivers, applications should take measures to handle
"UnknownTransactionCommitResult"
errors during transaction commits.
For example, the following helper commits a transaction and retries if
a "UnknownTransactionCommitResult"
is encountered:
- Mongo Shell
- Python
- Java (Sync)
- Node.js
- PHP
- Other
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Retry Transaction and Commit Operation¶
Incorporating logic to retrying the transaction for transient errors and retrying the commit, the full code example is:
- Mongo Shell
- Python
- Java (Sync)
- Node.js
- PHP
- Other
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.
Read Concern/Write Concern/Read Preference¶
Transactions and Read Concern¶
Operations in a transaction use the transaction-level read concern. That is, any read concern set at the collection and database level is ignored inside the transaction.
You can set the transaction-level read concern at the transaction start.
- If the transaction-level read concern is unset, the transaction-level read concern defaults to the session-level read concern.
- If transaction-level and the session-level read concern are unset,
the transaction-level read concern defaults to the client-level read
concern. By default, client-level read concern is
"local"
for reads against the primary. See also Transactions and Read Preference.
Multi-document transactions support the following read concern levels:
"local"
¶
- Read concern
"local"
returns the most recent data available from the node but can be rolled back.
"majority"
¶
- Read concern
"majority"
returns data that has been acknowledged by a majority of the replica set members (i.e. data cannot be rolled back) if the transaction commits with write concern “majority”. [1] - If the transaction does not use write concern “majority” for the commit, the
"majority"
read concern provides no guarantees that read operations read majority-committed data.
[1] | For a three-member Primary-Secondary-Arbiter (PSA) replica set
architecture, you may have disabled read concern “majority” to avoid cache pressure.
Disabling "majority" does not affect transactions;
i.e. you can specify read concern "majority" for
transactions even if read concern "majority" is
disabled. |
"snapshot"
¶
- Read concern
"snapshot"
returns data from a snapshot of majority committed data if the transaction commits with write concern “majority”. - If the transaction does not use write concern “majority” for the commit, the
"snapshot"
read concern provides no guarantee that read operations used a snapshot of majority-committed data.
Transactions and Write Concern¶
Transactions use the transaction-level write concern to commit the write operations. Operations inside transactions ignore write concerns.
Tip
Do not explicitly set the write concern for the individual write operations inside a transaction.
You can set the transaction-level write concern at the transaction start:
- If the transaction-level write concern is unset, the transaction-level write concern defaults to the session-level write concern for the commit.
- If the transaction-level write concern and the session-level write
concern are unset, transaction-level write concern defaults to the
client-level write concern. By default, client-level write concern
is
w: 1
.
Multi-document transactions support the following write concern w
values:
w: 1
¶
Write concern
w: 1
returns acknowledgement after the commit has been applied to the primary.Important
When you commit with
w: 1
, your transaction can be rolled back if there is a failover.When you commit with
w: 1
write concern, transaction-level"majority"
read concern provides no guarantees that read operations in the transaction read majority-committed data.When you commit with
w: 1
write concern, transaction-level"snapshot"
read concern provides no guarantee that read operations in the transaction used a snapshot of majority-committed data.
w: "majority"
¶
- Write concern
w: "majority"
returns acknowledgement after the commit has been applied to a majority (M) of voting members; i.e. the commit has been applied to the primary and (M-1) voting secondaries. - When you commit with
w: "majority"
write concern, transaction-level"majority"
read concern guarantees that operations have read majority-committed data. - When you commit with
w: "majority"
write concern, transaction-level"snapshot"
read concern guarantees that operations have from a synchronized snapshot of majority-committed data.
Transactions and Read Preference¶
Operations in a transaction use the transaction-level read preference.
Using the drivers, you can set the transaction-level read preference at the transaction start:
- If the transaction-level read preference is unset, the transaction uses the session-level read preference.
- If transaction-level and the session-level read preference are unset,
the transaction uses the client-level read preference. By default,
the client-level read preference is
primary
.
Multi-document transactions that contain
read operations must use read preference primary
.
All operations in a given transaction must route to the same member.
General Information¶
Feature Compatibility Version (FCV)¶
The featureCompatibilityVersion
(fCV) of all members of the replica
set must be 4.0
or greater. To check the fCV for a member, connect
to the member and run the following command:
For more information on fCV, see
setFeatureCompatibilityVersion
.
Storage Engines¶
Multi-document transactions are only available for deployments that use WiredTiger storage engine.
Multi-document transactions are not available for deployments that use in-memory storage engine or the deprecated MMAPv1 storage engine.
Diagnostics¶
- The
db.serverStatus()
method/serverStatus
command returns transactions metrics. - The
$currentOp
aggregation pipeline returns$currentOp.transaction
information for an operation if that operation is part of a transaction. You can also use$currentOp
to find inactive sessions that are holding locks as part of a transaction.
Transactions and Security¶
- If running with access control, you must have privileges for the operations in the transaction. [2]
- If running with auditing, operations in an aborted transaction are still audited. However, there is no audit event that indicates that the transaction aborted.
[2] | If using $external authentication users (i.e. Kerberos, LDAP,
x.509 users), the usernames cannot be greater than 10k bytes. |