# `client_session` – Logical sessions for sequential operations

Logical sessions for ordering sequential operations.

Added in version 3.6.

## Causally Consistent Reads

    async with client.start_session(causal_consistency=True) as session:
        collection = client.db.collection
        await collection.update_one({"_id": 1}, {"$set": {"x": 10}}, session=session)
        secondary_c = collection.with_options(read_preference=ReadPreference.SECONDARY)

        # A secondary read waits for replication of the write.
        await secondary_c.find_one({"_id": 1}, session=session)

If causal_consistency is True (the default), read operations that use the session are causally after previous read and write operations. Using a causally consistent session, an application can read its own writes and is guaranteed monotonic reads, even when reading from replica set secondaries.

See also

The MongoDB documentation on causal-consistency.

## Transactions

Added in version 3.7.

MongoDB 4.0 adds support for transactions on replica set primaries. A transaction is associated with a `AsyncClientSession`. To start a transaction on a session, use `AsyncClientSession.start_transaction()` in a with-statement. Then, execute an operation within the transaction by passing the session to the operation:

    orders = client.db.orders
    inventory = client.db.inventory
    async with client.start_session() as session:
        async with await session.start_transaction():
            await orders.insert_one({"sku": "abc123", "qty": 100}, session=session)
            await inventory.update_one(
                {"sku": "abc123", "qty": {"$gte": 100}},
                {"$inc": {"qty": -100}},
                session=session,
            )

Upon normal completion of `async with await session.start_transaction()` block, the transaction automatically calls `AsyncClientSession.commit_transaction()`. If the block exits with an exception, the transaction automatically calls `AsyncClientSession.abort_transaction()`.

In general, multi-document transactions only support read/write (CRUD) operations on existing collections. However, MongoDB 4.4 adds support for creating collections and indexes with some limitations, including an insert operation that would result in the creation of a new collection. For a complete description of all the supported and unsupported operations see the MongoDB server’s documentation for transactions.

A session may only have a single active transaction at a time, multiple transactions on the same session can be executed in sequence.

### Sharded Transactions

Added in version 3.9.

PyMongo 3.9 adds support for transactions on sharded clusters running MongoDB >=4.2. Sharded transactions have the same API as replica set transactions. When running a transaction against a sharded cluster, the session is pinned to the mongos server selected for the first operation in the transaction. All subsequent operations that are part of the same transaction are routed to the same mongos server. When the transaction is completed, by running either commitTransaction or abortTransaction, the session is unpinned.

See also

The MongoDB documentation on transactions.

## Snapshot Reads

Added in version 3.12.

MongoDB 5.0 adds support for snapshot reads. Snapshot reads are requested by passing the `snapshot` option to `start_session()`. If `snapshot` is True, all read operations that use this session read data from the same snapshot timestamp. The server chooses the latest majority-committed snapshot timestamp when executing the first read operation using the session. Subsequent reads on this session read from the same snapshot timestamp. Snapshot reads are also supported when reading from replica set secondaries.

    # Each read using this session reads data from the same point in time.
    async with client.start_session(snapshot=True) as session:
        order = await orders.find_one({"sku": "abc123"}, session=session)
        inventory = await inventory.find_one({"sku": "abc123"}, session=session)

### Snapshot Reads Limitations

Snapshot reads sessions are incompatible with `causal_consistency=True`. Only the following read operations are supported in a snapshot reads session:

- `find()`

- `find_one()`

- `aggregate()`

- `count_documents()`

- `distinct()` (on unsharded collections)

## Classes

class pymongo.asynchronous.client_session.AsyncClientSession(client, server_session, options, implicit)

  A session for ordering sequential operations.

  `AsyncClientSession` instances are not thread-safe or fork-safe. They can only be used by one thread or process at a time. A single `AsyncClientSession` cannot be used to run multiple operations concurrently.

  Should not be initialized directly by application developers - to create a `AsyncClientSession`, call `start_session()`.

  Parameters:

    - client (AsyncMongoClient[Any])

    - server_session (Any)

    - options (SessionOptions)

    - implicit (bool)

  async abort_transaction()

    Abort a multi-statement transaction.

    Added in version 3.7.

    Return type:

      None

  advance_cluster_time(cluster_time)

    Update the cluster time for this session.

    Parameters:

      cluster_time (Mapping[str, Any]) – The `cluster_time` from another AsyncClientSession instance.

    Return type:

      None

  advance_operation_time(operation_time)

    Update the operation time for this session.

    Parameters:

      operation_time (Timestamp) – The `operation_time` from another AsyncClientSession instance.

    Return type:

      None

  bind(end_session=True)

    Bind this session so it is implicitly passed to all database operations within the returned context.

        async with client.start_session() as s:
            async with s.bind():
                # session=s is passed implicitly
                await client.db.collection.insert_one({"x": 1})

    Parameters:

      end_session (bool) – Whether to end the session on exiting the returned context. Defaults to True. If set to False, `end_session()` must be called once the session is no longer used.

    Return type:

      _AsyncBoundSessionContext

    Added in version 4.17.

  property client: AsyncMongoClient[Any]

    The `AsyncMongoClient` this session was created from.

  property cluster_time: ClusterTime | None

    The cluster time returned by the last operation executed in this session.

  async commit_transaction()

    Commit a multi-statement transaction.

    Added in version 3.7.

    Return type:

      None

  async end_session()

    Finish this session. If a transaction has started, abort it.

    It is an error to use the session after the session has ended.

    Return type:

      None

  property has_ended: bool

    True if this session is finished.

  property in_transaction: bool

    True if this session has an active multi-statement transaction.

    Added in version 3.10.

  property operation_time: Timestamp | None

    The operation time returned by the last operation executed in this session.

  property options: SessionOptions

    The `SessionOptions` this session was created with.

  property session_id: Mapping[str, Any]

    A BSON document, the opaque server session identifier.

  async start_transaction(read_concern=None, write_concern=None, read_preference=None, max_commit_time_ms=None)

    Start a multi-statement transaction.

    Takes the same arguments as `TransactionOptions`.

    Changed in version 3.9: Added the `max_commit_time_ms` option.

    Added in version 3.7.

    Parameters:

      - read_concern (ReadConcern | None)

      - write_concern (WriteConcern | None)

      - read_preference (_ServerMode | None)

      - max_commit_time_ms (int | None)

    Return type:

      AsyncContextManager[Any, bool | None]

  async with_transaction(callback, read_concern=None, write_concern=None, read_preference=None, max_commit_time_ms=None)

    Execute a callback in a transaction.

    This method starts a transaction on this session, executes `callback` once, and then commits the transaction. For example:

        async def callback(session):
            orders = session.client.db.orders
            inventory = session.client.db.inventory
            await orders.insert_one({"sku": "abc123", "qty": 100}, session=session)
            await inventory.update_one({"sku": "abc123", "qty": {"$gte": 100}},
                                 {"$inc": {"qty": -100}}, session=session)

        async with client.start_session() as session:
            await session.with_transaction(callback)

    To pass arbitrary arguments to the `callback`, wrap your callable with a `lambda` like this:

        async def callback(session, custom_arg, custom_kwarg=None):
            # Transaction operations...

        async with client.start_session() as session:
            await session.with_transaction(
                lambda s: callback(s, "custom_arg", custom_kwarg=1))

    In the event of an exception, `with_transaction` may retry the commit or the entire transaction, therefore `callback` may be invoked multiple times by a single call to `with_transaction`. Developers should be mindful of this possibility when writing a `callback` that modifies application state or has any other side-effects. Note that even when the `callback` is invoked multiple times, `with_transaction` ensures that the transaction will be committed at-most-once on the server.

    The `callback` should not attempt to start new transactions, but should simply run operations meant to be contained within a transaction. The `callback` should also not commit the transaction; this is handled automatically by `with_transaction`. If the `callback` does commit or abort the transaction without error, however, `with_transaction` will return without taking further action.

    `AsyncClientSession` instances are not thread-safe or fork-safe. Consequently, the `callback` must not attempt to execute multiple operations concurrently.

    When `callback` raises an exception, `with_transaction` automatically aborts the current transaction. When `callback` or `commit_transaction()` raises an exception that includes the `"TransientTransactionError"` error label, `with_transaction` starts a new transaction and re-executes the `callback`.

    The `callback` MUST NOT silently handle command errors without allowing such errors to propagate. Command errors may abort the transaction on the server, and an attempt to commit the transaction will be rejected with a `NoSuchTransaction` error. For more information see the transactions specification.

    When `commit_transaction()` raises an exception with the `"UnknownTransactionCommitResult"` error label, `with_transaction` retries the commit until the result of the transaction is known.

    This method will cease retrying after 120 seconds has elapsed. This timeout is not configurable and any exception raised by the `callback` or by `AsyncClientSession.commit_transaction()` after the timeout is reached will be re-raised. Applications that desire a different timeout duration should not use this method.

    Parameters:

      - callback (Callable[[AsyncClientSession], Awaitable[_T]]) – The callable `callback` to run inside a transaction. The callable must accept a single argument, this session. Note, under certain error conditions the callback may be run multiple times.

      - read_concern (ReadConcern | None) – The `ReadConcern` to use for this transaction.

      - write_concern (WriteConcern | None) – The `WriteConcern` to use for this transaction.

      - read_preference (_ServerMode | None) – The read preference to use for this transaction. If `None` (the default) the `read_preference` of this `AsyncDatabase` is used. See `read_preferences` for options.

      - max_commit_time_ms (int | None)

    Returns:

      The return value of the `callback`.

    Return type:

      _T

    Added in version 3.9.

class pymongo.asynchronous.client_session.SessionOptions(causal_consistency=None, default_transaction_options=None, snapshot=False)

  Options for a new `AsyncClientSession`.

  Parameters:

    - causal_consistency (Optional[bool]) – If True, read operations are causally ordered within the session. Defaults to True when the `snapshot` option is `False`.

    - default_transaction_options (Optional[TransactionOptions]) – The default TransactionOptions to use for transactions started on this session.

    - snapshot (Optional[bool]) – If True, then all reads performed using this session will read from the same snapshot. This option is incompatible with `causal_consistency=True`. Defaults to `False`.

  Changed in version 3.12: Added the `snapshot` parameter.

  property causal_consistency: bool

    Whether causal consistency is configured.

  property default_transaction_options: TransactionOptions | None

    The default TransactionOptions to use for transactions started on this session.

    Added in version 3.7.

  property snapshot: bool | None

    Whether snapshot reads are configured.

    Added in version 3.12.

class pymongo.asynchronous.client_session.TransactionOptions(read_concern=None, write_concern=None, read_preference=None, max_commit_time_ms=None)

  Options for `AsyncClientSession.start_transaction()`.

  Parameters:

    - read_concern (Optional[ReadConcern]) – The `ReadConcern` to use for this transaction. If `None` (the default) the `read_preference` of the `AsyncMongoClient` is used.

    - write_concern (Optional[WriteConcern]) – The `WriteConcern` to use for this transaction. If `None` (the default) the `read_preference` of the `AsyncMongoClient` is used.

    - read_preference (Optional[_ServerMode]) – The read preference to use. If `None` (the default) the `read_preference` of this `AsyncMongoClient` is used. See `read_preferences` for options. Transactions which read must use `PRIMARY`.

    - max_commit_time_ms (Optional[int]) – The maximum amount of time to allow a single commitTransaction command to run. This option is an alias for maxTimeMS option on the commitTransaction command. If `None` (the default) maxTimeMS is not used.

  Changed in version 3.9: Added the `max_commit_time_ms` option.

  Added in version 3.7.

  property max_commit_time_ms: int | None

    The maxTimeMS to use when running a commitTransaction command.

    Added in version 3.9.

  property read_concern: ReadConcern | None

    This transaction’s `ReadConcern`.

  property read_preference: _ServerMode | None

    This transaction’s `ReadPreference`.

  property write_concern: WriteConcern | None

    This transaction’s `WriteConcern`.