Docs Menu
Docs Home
/ / /
Rust Driver
/

Transactions

On this page

  • Overview
  • Methods
  • Example
  • Additional Information
  • API Documentation

In this guide, you can learn how to use the Rust driver to perform transactions. Transactions allow you to perform a series of operations that change data only if the entire transaction is committed. If any operation in the transaction does not succeed, the driver stops the transaction and discards all data changes before they ever become visible. This feature is called atomicity.

In MongoDB, transactions run within logical sessions. A session is a grouping of related read or write operations that you want to run sequentially. Sessions enable causal consistency for a group of operations and allow you to run operations in an ACID-compliant transaction, which is a transaction that meets an expectation of atomicity, consistency, isolation, and durability. MongoDB guarantees that the data involved in your transaction operations remains consistent, even if the operations encounter unexpected errors.

When using the Rust driver, you can create a new session from a Client instance as a ClientSession type. You can improve your app's performance by reusing your client for multiple sessions and transactions instead of instantiating a new client each time.

Warning

Use a ClientSession only in operations running on the Client that created it. Using a ClientSession with a different Client results in operation errors.

Create a ClientSession by using the start_session() method on your Client instance. You can then modify the session state using the methods provided by the ClientSession type. The following table describes these methods:

Method
Description
start_transaction()
Starts a new transaction on this session. The session must be passed into each operation within the transaction, or the operation will run outside of the transaction.

You can set transaction options by chaining TransactionOptions option builder methods to start_transaction().

Errors returned from operations run within the transaction might include a TRANSIENT_TRANSACTION_ERROR label, which indicates that the entire transaction can be ended, then retried with the expectation that it will succeed.
commit_transaction()
Commits the active transaction for this session. This method returns an error if there is no active transaction for the session or the transaction was previously ended.

This method might return an error that includes an UNKNOWN_TRANSACTION_COMMIT_RESULT label, which indicates that it is unknown if the committed transaction satisfies the set write concern. If you encounter this error, it is safe to retry the commit until the write concern is satisfied or the method returns an error without the label.
abort_transaction()
Ends the active transaction for this session. This method returns an error if there is no active transaction for the session or if the transaction was committed or ended.
and_run()
Runs the given callback, then commits or ends the transaction. The driver retries callbacks and commits that raise an error with a TRANSIENT_TRANSACTION_ERROR label. If they raise any other error, the driver ends the transaction and returns the error to the caller. When you use this method to perform a transaction, the driver automatically handles any errors, so you can choose to omit error handling code.

Because the callback returns a future and can be run multiple times, the Rust language closure borrowing rules for captured values can be restrictive. So, the and_run() method accepts a context parameter that is passed to the callback.

Parameters: context C, callback FnMut(&'a mut ClientSession, &'a mut C)

Important

Methods That Can Run in Transactions

To run MongoDB operations within transactions, you must chain the session() method to the operation. This method accepts a ClientSession instance as a parameter.

For example, to delete a document, you can generally use the delete_one() method. However, to delete a document within a transaction, you must chain the session() method to delete_one() and pass the session as a parameter.

The following code defines the insert_media() callback function that inserts data into the books and films collections:

async fn insert_media(session: &mut ClientSession) -> Result<(), Error> {
let books_coll = session
.client()
.database("db")
.collection::<Document>("books");
let films_coll = session
.client()
.database("db")
.collection::<Document>("films");
books_coll
.insert_one(doc! {
"name": "Sula",
"author": "Toni Morrison"
})
.session(&mut *session)
.await?;
films_coll
.insert_one(doc! {
"name": "Nostalgia",
"year": 1983
})
.session(&mut *session)
.await?;
Ok(())
}

The following code completes the following actions to perform the transaction:

  1. Creates a session from the client by using the start_session() method.

  2. Calls the start_transaction() method to start a transaction.

  3. Calls the and_run() method to run the insert_media() callback function within the transaction.

let mut session = client.start_session().await?;
session
.start_transaction()
.and_run((), |session, _| insert_media(session).boxed())
.await?;
println!("Successfully committed transaction!");
Successfully committed transaction!

If you require more control over your transactions, see the ClientSession API documentation to find an example that shows how to manually create and commit a transaction.

To learn more about the concepts mentioned in this guide, see the following pages in the Server manual:

To learn more about ACID compliance, see the What are ACID Properties in Database Management Systems? article on the MongoDB website.

To learn more about insert operations, see the Insert Documents guide.

To learn more about the methods and types mentioned in this guide, see the following API documentation:

Back

Atlas Search Indexes