MONGOC_CLIENT...RT_TRANSACTION(3)

hey bestie πŸ’– welcome to the libmongoc manual β€” this page is MONGOC_CLIENT...RT_TRANSACTION(3), and it’s literally about starting a multi-document transaction. it’s giving very β€œgroup project but make it transactional” energy. let’s get into it 🫢


✨ SYNOPSIS ✨

          bool
          mongoc_client_session_start_transaction (mongoc_client_session_t *session,
                                                   const mongoc_transaction_opt_t *opts,
                                                   bson_error_t *error);

okay so here’s the tea β˜•: this starts a multi-document transaction for all the following operations in this session.

any options you pass in opts override options passed to mongoc_session_opts_set_default_transaction_opts(), and options inherited from the mongoc_client_t. the opts argument is copied, so you can free it after calling this function β€” yes bestie, free it, it’s fine πŸ’…

the transaction must be completed with mongoc_client_session_commit_transaction() or mongoc_client_session_abort_transaction(). an in-progress transaction is automatically aborted by mongoc_client_session_destroy().

heads up: if a command inside the transaction fails, it may cause the transaction on the server to be aborted. an attempt to commit such a transaction will be rejected with NoSuchTransaction error. 😭

πŸŽ€ PARAMETERS πŸŽ€

  • session: A mongoc_client_session_t.
  • opts: A mongoc_transaction_opt_t or NULL.
  • error: An optional location for a bson_error_t or NULL.

πŸ’… RETURN πŸ’…

returns true if the transaction was started. returns false and sets error if there are invalid arguments, such as a session with a transaction already in progress. periodt.


🌈 EXAMPLE 🌈

the following example demonstrates how to use error labels to reliably execute a multi-document transaction despite network errors and other transient failures. it’s iconic, honestly.

example-transaction.c

          /* gcc example-transaction.c -o example-transaction \
           *     $(pkg-config --cflags --libs libmongoc-1.0) */

          /* ./example-transaction [CONNECTION_STRING] */

          #include <mongoc/mongoc.h>

          #include <stdio.h>

          int
          main(int argc, char *argv[])
          {
             int exit_code = EXIT_FAILURE;

             mongoc_client_t *client = NULL;
             mongoc_database_t *database = NULL;
             mongoc_collection_t *collection = NULL;
             mongoc_client_session_t *session = NULL;
             mongoc_session_opt_t *session_opts = NULL;
             mongoc_transaction_opt_t *default_txn_opts = NULL;
             mongoc_transaction_opt_t *txn_opts = NULL;
             mongoc_read_concern_t *read_concern = NULL;
             mongoc_write_concern_t *write_concern = NULL;
             const char *uri_string = "mongodb://127.0.0.1/?appname=transaction-example";
             mongoc_uri_t *uri;
             bson_error_t error;
             bson_t *doc = NULL;
             bson_t *insert_opts = NULL;
             int32_t i;
             int64_t start;
             bson_t reply = BSON_INITIALIZER;
             char *reply_json;
             bool r;

             mongoc_init();

             if (argc > 1) {
                uri_string = argv[1];
             }

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI:\n"
                        "error message: %s\n",
                        error.message);
                goto done;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                goto done;
             }

             mongoc_client_set_error_api(client, 2);
             database = mongoc_client_get_database(client, "example-transaction");

             /* inserting into a nonexistent collection normally creates it, but a
              * collection can't be created in a transaction; create it now */
             collection = mongoc_database_create_collection(database, "collection", NULL, &error);

             if (!collection) {
                /* code 48 is NamespaceExists, see error_codes.err in mongodb source */
                if (error.code == 48) {
                   collection = mongoc_database_get_collection(database, "collection");
                } else {
                   fprintf(stderr, "Failed to create collection: %s\n", error.message);
                   goto done;
                }
             }

             /* a transaction's read preferences, read concern, and write concern can be
              * set on the client, on the default transaction options, or when starting
              * the transaction. for the sake of this example, set read concern on the
              * default transaction options. */
             default_txn_opts = mongoc_transaction_opts_new();
             read_concern = mongoc_read_concern_new();
             mongoc_read_concern_set_level(read_concern, "snapshot");
             mongoc_transaction_opts_set_read_concern(default_txn_opts, read_concern);
             session_opts = mongoc_session_opts_new();
             mongoc_session_opts_set_default_transaction_opts(session_opts, default_txn_opts);

             session = mongoc_client_start_session(client, session_opts, &error);
             if (!session) {
                fprintf(stderr, "Failed to start session: %s\n", error.message);
                goto done;
             }

             /* in this example, set write concern when starting the transaction */
             txn_opts = mongoc_transaction_opts_new();
             write_concern = mongoc_write_concern_new();
             mongoc_write_concern_set_wmajority(write_concern, 1000 /* wtimeout */);
             mongoc_transaction_opts_set_write_concern(txn_opts, write_concern);

             insert_opts = bson_new();
             if (!mongoc_client_session_append(session, insert_opts, &error)) {
                fprintf(stderr, "Could not add session to opts: %s\n", error.message);
                goto done;
             }

          retry_transaction:
             r = mongoc_client_session_start_transaction(session, txn_opts, &error);
             if (!r) {
                fprintf(stderr, "Failed to start transaction: %s\n", error.message);
                goto done;
             }

             /* insert two documents - on error, retry the whole transaction */
             for (i = 0; i < 2; i++) {
                doc = BCON_NEW("_id", BCON_INT32(i));
                bson_destroy(&reply);
                r = mongoc_collection_insert_one(collection, doc, insert_opts, &reply, &error);

                bson_destroy(doc);

                if (!r) {
                   fprintf(stderr, "Insert failed: %s\n", error.message);
                   mongoc_client_session_abort_transaction(session, NULL);

                   /* a network error, primary failover, or other temporary error in a
                    * transaction includes {"errorLabels": ["TransientTransactionError"]},
                    * meaning that trying the entire transaction again may succeed
                    */
                   if (mongoc_error_has_label(&reply, "TransientTransactionError")) {
                      goto retry_transaction;
                   }

                   goto done;
                }

                reply_json = bson_as_relaxed_extended_json(&reply, NULL);
                printf("%s\n", reply_json);
                bson_free(reply_json);
             }

             /* in case of transient errors, retry for 5 seconds to commit transaction */
             start = bson_get_monotonic_time();
             while (bson_get_monotonic_time() - start < 5 * 1000 * 1000) {
                bson_destroy(&reply);
                r = mongoc_client_session_commit_transaction(session, &reply, &error);
                if (r) {
                   /* success */
                   break;
                } else {
                   fprintf(stderr, "Warning: commit failed: %s\n", error.message);
                   if (mongoc_error_has_label(&reply, "TransientTransactionError")) {
                      goto retry_transaction;
                   } else if (mongoc_error_has_label(&reply, "UnknownTransactionCommitResult")) {
                      /* try again to commit */
                      continue;
                   }

                   /* unrecoverable error trying to commit */
                   break;
                }
             }

             exit_code = EXIT_SUCCESS;

          done:
             bson_destroy(&reply);
             bson_destroy(insert_opts);
             mongoc_write_concern_destroy(write_concern);
             mongoc_read_concern_destroy(read_concern);
             mongoc_transaction_opts_destroy(txn_opts);
             mongoc_transaction_opts_destroy(default_txn_opts);
             mongoc_client_session_destroy(session);
             mongoc_collection_destroy(collection);
             mongoc_database_destroy(database);
             mongoc_uri_destroy(uri);
             mongoc_client_destroy(client);

             mongoc_cleanup();

             return exit_code;
          }

πŸ‘‘ AUTHOR πŸ‘‘

MongoDB, Inc


2009-present, MongoDB, Inc.


made with πŸ’– by MongoDB, Inc β€” copyright 2009-present, MongoDB, Inc. this page comes from libmongoc version 2.5.6, dated Oct 09, 2026. bye bestie, go start that transaction! 🫢✨

πŸ“¦ where this page comes from