Docs Menu
Docs Home
/
MongoDB Manual
/ / / /

Session.abortTransaction()

On this page

  • Definition
  • Behavior
  • Example
Session.abortTransaction()

Terminates the multi-document transaction and rolls back any data changes made by the operations within the transaction. That is, the transaction ends without saving any of the changes made by the operations in the transaction.

Important

mongosh Method

This page documents a mongosh method. This is not the documentation for database commands or language-specific drivers, such as Node.js.

For the database command, see the abortTransaction command.

For MongoDB API drivers, refer to the language-specific MongoDB driver documentation.

For the legacy mongo shell documentation, refer to the documentation for the corresponding MongoDB Server release:

Changed in version 4.2: Starting in MongoDB 4.2, multi-document transactions are available for both sharded clusters and replica sets.

When a transaction aborts, all data changes made by the writes in the transaction are discarded without ever becoming visible and the transaction ends.

If running with auditing, operations in an aborted transaction are still audited.

If the abort operation encounters an error, MongoDB drivers retry the abort operation a single time regardless of whether retryWrites is set to true. For more information, see Transaction Error Handling.

Consider a scenario where as changes are made to an employee's record in the hr database, you want to ensure that the events collection in the reporting database are in sync with the hr changes and vice versa. That is, you want to ensure that these writes are done as a single transaction, such that either both operations succeed or fail.

The employees collection in the hr database has the following documents:

{ "_id" : ObjectId("5af0776263426f87dd69319a"), "employee" : 3, "name" : { "title" : "Mr.", "name" : "Iba Ochs" }, "status" : "Active", "department" : "ABC" }
{ "_id" : ObjectId("5af0776263426f87dd693198"), "employee" : 1, "name" : { "title" : "Miss", "name" : "Ann Thrope" }, "status" : "Active", "department" : "ABC" }
{ "_id" : ObjectId("5af0776263426f87dd693199"), "employee" : 2, "name" : { "title" : "Mrs.", "name" : "Eppie Delta" }, "status" : "Active", "department" : "XYZ" }

The employees collection has a unique index on the employee field:

db.employees.createIndex( { employee: 1 }, { unique: true } )

The events collection in the reporting database has the following documents:

{ "_id" : ObjectId("5af07daa051d92f02462644a"), "employee" : 1, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } }
{ "_id" : ObjectId("5af07daa051d92f02462644b"), "employee" : 2, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "XYZ", "old" : null } }
{ "_id" : ObjectId("5af07daa051d92f02462644c"), "employee" : 3, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } }

The following example opens a transaction, attempts to add a record to the events collection and add a document to the employees collection. If the operation encounters an error in either operations or in committing the transaction, the session aborts the transaction.

// Runs the txnFunc and retries if TransientTransactionError encountered
function runTransactionWithRetry(txnFunc, session) {
while (true) {
try {
txnFunc(session); // performs transaction
break;
} catch (error) {
// If transient error, retry the whole transaction
if ( error.hasOwnProperty("errorLabels") && error.errorLabels.includes("TransientTransactionError") ) {
print("TransientTransactionError, retrying transaction ...");
continue;
} else {
throw error;
}
}
}
}
// Retries commit if UnknownTransactionCommitResult encountered
function commitWithRetry(session) {
while (true) {
try {
session.commitTransaction(); // Uses write concern set at transaction start.
print("Transaction committed.");
break;
} catch (error) {
// Can retry commit
if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes("UnknownTransactionCommitResult") ) {
print("UnknownTransactionCommitResult, retrying commit operation ...");
continue;
} else {
print("Error during commit ...");
throw error;
}
}
}
}
// Performs inserts and count in a transaction
function updateEmployeeInfo(session) {
employeesCollection = session.getDatabase("hr").employees;
eventsCollection = session.getDatabase("reporting").events;
// Start a transaction for the session that uses:
// - read concern "snapshot"
// - write concern "majority"
session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );
try{
eventsCollection.insertOne(
{ employee: 3, status: { new: "Active", old: null }, department: { new: "XYZ", old: null } }
);
// Count number of events for employee 3
var countDoc = eventsCollection.aggregate( [ { $match: { employee: 3 } }, { $count: "eventCounts" } ] ).next();
print( "events count (in active transaction): " + countDoc.eventCounts );
// The following operations should fail as an employee ``3`` already exist in employees collection
employeesCollection.insertOne(
{ employee: 3, name: { title: "Miss", name: "Terri Bachs" }, status: "Active", department: "XYZ" }
);
} catch (error) {
print("Caught exception during transaction, aborting.");
session.abortTransaction();
throw error;
}
commitWithRetry(session);
} // End of updateEmployeeInfo function
// Start a session.
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
try{
runTransactionWithRetry(updateEmployeeInfo, session);
} catch (error) {
// Do something with error
} finally {
session.endSession();
}

Tip

See also:

Back

Session