Transactions
On this page
Overview
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.
Transaction APIs
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
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.
Core API
Alternatively, you can have more control over your transaction lifecyle
by using the following functions with your mongoc_client_session_t
instance:
Function | Description |
---|---|
| 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. |
| 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. |
| 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. |
| 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.
Transaction Example
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:
Defines the callback function, which receives the
mongoc_client_session_t
instance as a parameter.Creates
mongoc_collection_t
instances to access the target collections.Specifies the account number and amount to be transferred between accounts.
Updates the customer's balances to reflect the money transfer.
Records a receipt of the transaction with a timestamp.
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:
Creates a session from the client by using the
mongoc_client_start_session()
function.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.
Additional Information
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.
API Documentation
To learn more about any of the types or functions discussed in this guide, see the following API documentation: