Docs Menu
Docs Home
/ / /
C Driver
/

Transactions

On this page

  • Overview
  • Transaction APIs
  • Convenient API
  • Core API
  • Transaction Example
  • Additional Information
  • API Documentation

In this guide, you can learn how to use the C 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 library 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 intend 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 C driver, you can create a new session from a mongoc_client_t instance. Then, you can use the resulting mongoc_client_session_t instance to perform transactions.

Warning

Use a mongoc_client_session_t only with the mongoc_client_t (or associated mongoc_database_t or mongoc_collection_t) that created it. Using a mongoc_client_session_t with a different mongoc_client_t results in operation errors.

In this section, you can learn about the transaction APIs provided by the C driver. Before you begin a transaction, you must create a mongoc_client_session_t by using the mongoc_client_start_session() function on your mongoc_client_t instance. Then, you can use either of the following APIs to perform a transaction:

  • Convenient API

  • Core API

The C driver provides a Convenient Transaction API to manage the transaction lifecyle. Implement this API by using the mongoc_client_session_with_transaction() function to run custom callback within a transaction. The mongoc_client_session_with_transaction() function performs the following tasks:

  • Starts the transaction

  • Handles errors by either ending the transaction or retrying it, such as when the operation results in a TransientTransactionError

  • Commits the transaction

The Transaction Example section of this guide demonstrates how to use this API to perform a transaction.

Alternatively, you can have more control over your transaction lifecyle by using the following functions with your mongoc_client_session_t instance:

Function
Description

mongoc_client_session_start_transaction()

Starts a new transaction, configured with the given options, on this session. Returns false and sets the provided error if there are invalid arguments, such as a session with a transaction already in progress. To learn more about this function, see the startTransaction() page in the Server manual.

mongoc_client_session_abort_transaction()

Ends the active transaction for this session. Returns false and sets the provided error if there is no active transaction for the session or the transaction has been committed or ended. To learn more about this function, see the abortTransaction() page in the Server manual.

mongoc_client_session_commit_transaction()

Commits the active transaction for this session. Returns an error if there is no active transaction for the session or if the transaction was ended. To learn more about this function, see the commitTransaction() page in the Server manual.

mongoc_client_session_destroy()

Aborts any transactions in progress and ends this session. Frees all client resources associated with this session.

To learn more about functions that retrieve mongoc_client_session_t properties and modify mutable session properties, see the API documentation.

This example defines a callback function that modifies data in the collections of the sample_bank database for a banking transaction. The code performs the following actions:

  1. Defines the callback function, which receives the mongoc_client_session_t instance as a parameter.

  2. Creates mongoc_collection_t instances to access the target collections.

  3. Specifies the account number and amount to be transferred between accounts.

  4. Updates the customer's balances to reflect the money transfer.

  5. Records a receipt of the transaction with a timestamp.

  6. Prints a message if the transaction committed successfully.

bool
transaction_callback (mongoc_client_session_t *session, void *ctx, bson_t **reply,
bson_error_t *error)
{
BSON_UNUSED(ctx);
BSON_UNUSED(reply);
mongoc_client_t *client = mongoc_client_session_get_client (session);
mongoc_collection_t *checking = mongoc_client_get_collection (client, "sample_bank", "checking");
mongoc_collection_t *savings = mongoc_client_get_collection (client, "sample_bank", "savings");
mongoc_collection_t *receipts = mongoc_client_get_collection (client, "sample_bank", "receipts");
const char *account_id = "123456";
int transfer_amount = 1000;
bson_t *filter = BCON_NEW ("account_id", BCON_UTF8 (account_id));
bson_t *update_decrement = BCON_NEW ("$inc", "{", "balance", BCON_INT32 (-transfer_amount), "}");
bson_t *update_increment = BCON_NEW ("$inc", "{", "balance", BCON_INT32 (transfer_amount), "}");
if (!mongoc_collection_update_one (checking, filter, update_decrement, NULL, NULL, &error)) {
fprintf (stderr, "Failed to update checking account: %s\n", error.message);
return false;
}
if (!mongoc_collection_update_one (savings, filter, update_increment, NULL, NULL, &error)) {
fprintf (stderr, "Failed to update savings account: %s\n", error.message);
return false;
}
bson_t *receipt = BCON_NEW ("account_id", BCON_UTF8 (account_id),
"amount", BCON_INT32 (transfer_amount),
"timestamp", BCON_DATE_TIME (bson_get_monotonic_time ()));
if (!mongoc_collection_insert_one (receipts, receipt, NULL, NULL, &error)) {
fprintf (stderr, "Failed to insert receipt: %s\n", error.message);
return false;
}
mongoc_collection_destroy (checking);
mongoc_collection_destroy (savings);
mongoc_collection_destroy (receipts);
bson_destroy (filter);
bson_destroy (update_decrement);
bson_destroy (update_increment);
bson_destroy (receipt);
printf ("Transaction successful!");
return true;
}

Then, run the following code to perform the transaction. This code completes the following actions:

  1. Creates a session from the client by using the mongoc_client_start_session() function.

  2. Calls the mongoc_client_session_with_transaction() function to manage the transaction, passing the session and the callback as parameters.

mongoc_client_session_t *session = mongoc_client_start_session (client, NULL, NULL);
if (!session) {
fprintf (stderr, "Failed to start session\n");
mongoc_client_destroy (client);
return EXIT_FAILURE;
}
bool result =
mongoc_client_session_with_transaction (session,
(mongoc_client_session_with_transaction_cb_t) transaction_callback,
NULL, NULL, NULL, &error);
if (!result) {
fprintf (stderr, "Transaction error: %s\n", error.message);
}
mongoc_client_session_destroy (session);
mongoc_client_destroy (client);
mongoc_cleanup ();
Transaction successful!

Note

Parallel Operations Not Supported

The C driver does not support running parallel operations within a single transaction.

If you're using MongoDB Server v8.0 or later, you can perform write operations on multiple namespaces within a single transaction by using bulk write operations. For more information, see the Bulk Write Operations guide.

To learn more about the concepts mentioned in this guide, see the following pages in the MongoDB 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 any of the types or functions discussed in this guide, see the following API documentation:

Back

Bulk Write Operations