Open-Source Wikis

/

MongoDB

/

Features

/

Transactions

mongodb/mongo

Transactions

MongoDB supports multi-document, multi-statement, and (since 4.2) multi-shard ACID transactions. The data side is in src/mongo/db/transaction/ plus per-session state in src/mongo/db/session/. The router-side coordinator is the TransactionRouter in src/mongo/s/transaction_router.cpp.

Purpose

Transactions provide:

  • Atomicity across multiple documents and (with sharded transactions) multiple shards.
  • Snapshot isolation — reads see a consistent snapshot at a single cluster timestamp.
  • Retryable writes — a related but distinct mechanism that retries individual statements safely.

Single-shard transaction

sequenceDiagram
    autonumber
    participant Client
    participant Mongod
    participant TxnP as TransactionParticipant
    participant Storage

    Client->>Mongod: stmt 1 (txnNumber=N, autocommit=false, startTransaction=true)
    Mongod->>TxnP: beginOrContinue(N)
    TxnP->>Storage: open snapshot
    Storage-->>TxnP: snapshot at TS_N
    Mongod->>Mongod: run stmt 1 in WUOW
    Mongod-->>Client: ack

    Client->>Mongod: stmt 2 (txnNumber=N)
    Mongod->>TxnP: continue(N)
    Mongod->>Mongod: run stmt 2 in WUOW
    Mongod-->>Client: ack

    Client->>Mongod: commitTransaction
    Mongod->>TxnP: commit
    TxnP->>Storage: commit WUOW (single oplog entry with applyOps)
    Storage-->>TxnP: ok
    TxnP-->>Mongod: ok
    Mongod-->>Client: ok

Each transaction is identified by (lsid, txnNumber). The TransactionParticipant holds the per-session state, including the open WriteUnitOfWork and storage snapshot. On commit, the writes are batched into a single applyOps oplog entry so secondaries apply them atomically.

Multi-shard (cluster) transaction

When a transaction touches more than one shard, mongos orchestrates a cooperative two-phase commit:

graph TD
    Client -->|stmts| Router[TransactionRouter on mongos]
    Router -->|targeted stmts| ShardA
    Router -->|targeted stmts| ShardB
    Router -->|targeted stmts| ShardC

    Client -->|commit| Router
    Router -->|coordinate at ShardA| Coord[TransactionCoordinator on ShardA]
    Coord -->|prepare| ShardA
    Coord -->|prepare| ShardB
    Coord -->|prepare| ShardC
    ShardA -->|prepareTimestamp| Coord
    ShardB -->|prepareTimestamp| Coord
    ShardC -->|prepareTimestamp| Coord
    Coord -->|commitTimestamp = max(prepareTs)| ShardA
    Coord -->|commitTimestamp| ShardB
    Coord -->|commitTimestamp| ShardC

Steps:

  1. The router picks the at-cluster-time read snapshot — typically the cluster majority commit point.
  2. Each statement is routed to one or more shards with the snapshot pinned and autocommit=false.
  3. On commit, the router elects a coordinator (one of the participating shards) and sends coordinateCommitTransaction.
  4. The coordinator runs two-phase commit: send prepareTransaction to every participant, gather prepare timestamps, choose commitTimestamp = max(prepareTimestamp), and send commitTransaction to every participant.
  5. If any participant returns an error during prepare, the coordinator sends abortTransaction to all.

The router's state machine and the participants' prepare/commit logic together make up MongoDB's most intricate distributed protocol. The router-side implementation is in transaction_router.cpp (3.7 k lines) and tested in transaction_router_test.cpp (13 k lines); the data-side coordinator is in src/mongo/db/global_catalog/sharding_environment/transaction_coordinator*.cpp.

Read concerns and snapshots

Transactions use:

  • readConcern: "snapshot" — every read sees a single cluster-wide timestamp.
  • readConcern: "majority" — single-shard transactions can run with majority too, snapshotting at the local majority commit point.

The chosen snapshot is propagated as atClusterTime to every participating shard so that all reads, even cross-shard, observe the same view.

Retryable writes

Distinct from transactions, retryable writes let drivers safely retry single statements after a network or primary-failover error. The server stores a per-stmtId record in the session catalog so that a retry returns the same response without re-executing the write. Source: src/mongo/db/session/session_txn_record_*.cpp and the TransactionParticipant.

Internal transactions

Some server-side code (e.g. the resharding coordinator, the findAndModify upsert path) needs to run multi-statement transactions internally without a client lsid. The internal transactions framework (src/mongo/db/transaction/internal_transactions_feature_flag.idl and surrounding) provides synthetic session ids to scope these.

Session catalog

The session catalog (src/mongo/db/session/) tracks per-lsid state across sessions, transactions, retryable writes, and migrations:

  • SessionCatalog — global registry of (lsid, txnNumber) participants.
  • OperationSessionInfo — the per-request session metadata extracted from the command.
  • The config.transactions collection persists session state across primary failover.

Failure handling

  • Primary failover during a transaction — the new primary recovers the session catalog from config.transactions. Prepared transactions are resumed; in-progress un-prepared transactions are aborted.
  • Network errors during commit — the coordinator persists its decision before responding, so the router can retry coordinateCommitTransaction and get the same answer.
  • Stale shard versions — the router refreshes its routing cache and, depending on the protocol phase, may either retry the affected statement or abort the transaction.

Key source files

File Purpose
src/mongo/db/transaction/transaction_participant.cpp Per-session participant on mongod.
src/mongo/db/transaction/transaction_history_iterator.cpp Walks the oplog entries belonging to a transaction.
src/mongo/db/session/ Session catalog and per-session state.
src/mongo/s/transaction_router.cpp Cluster transaction state machine on mongos.
src/mongo/db/global_catalog/sharding_environment/ TransactionCoordinator on the elected shard.
src/mongo/db/transaction_validation.cpp Cross-cutting transaction validation rules.

Integration points

  • Replication — multi-statement transactions are persisted as applyOps oplog entries.
  • Sharding — every cluster transaction goes through the router and the catalog cache.
  • Op observer — emits prepare/commit/abort oplog entries.
  • Storage — provides the snapshot, prepared transaction support, and the timestamping primitives.
  • Change streams — see committed transactions as a single batch in their event stream.

Entry points for modification

Most transaction-related work touches the participant or the router. Adding a new error to the cluster transaction protocol means updating transaction_router.cpp, the participant, and the (very large) router test file. Changes to retryable writes are scoped to the session catalog. New cross-cutting validation goes in transaction_validation.cpp. The multi_statement_transaction* resmoke suites and the jstests/replsets/ and jstests/sharding/ transactions tests are the primary safety nets.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Transactions – MongoDB wiki | Factory