Mongo Shell
mongo "mongodb+srv://admatic-cluster-7qyyr.mongodb.net/test" --username admatic
MongoDB shell version v4.0.6
Enter password:
Implicit session: session { "id" : UUID("60f1c2ab-2e30-4ff0-9b73-12a03b503d1d") }
MongoDB server version: 4.0.6
MongoDB Enterprise Admatic-Cluster-shard-0:PRIMARY>
Create the collections
use hr
db.createCollection("employees")
db.createCollection("events")
db.employees.insert({ employee: 3, status: "Active" })
WriteResult({ "nInserted" : 1 })
Retry Transaction
// Runs the txnFunc and retries if TransientTransactionError encountered
function runTransactionWithRetry(txnFunc, session) {
while (true) {
try {
txnFunc(session); // performs transaction
break;
} catch (error) {
print("Transaction aborted. Caught exception during transaction.");
// If transient error, retry the whole transaction
if ( error.hasOwnProperty("errorLabels") && error.errorLabels.includes( "TransientTransactionError") ) {
print("TransientTransactionError, retrying transaction ...");
continue;
} else {
throw error;
}
}
}
}
Retry Commit Operation
// 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;
}
}
}
}
Updates two collections in a transactions
function updateEmployeeInfo(session) {
employeesCollection = session.getDatabase("hr").employees;
eventsCollection = session.getDatabase("hr").events;
session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );
try{
employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } );
eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } );
} catch (error) {
print("Caught exception during transaction, aborting.");
session.abortTransaction();
throw error;
}
commitWithRetry(session);
}
Start a session
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
session { "id" : UUID("0f41cae7-562b-40d2-880d-f19b623e7dcb") }
Run Transaction With Retry
try{
runTransactionWithRetry(updateEmployeeInfo, session);
} catch (error) {
// Do something with error
} finally {
session.endSession();
}
Transaction committed.
Verify
db.employees.find()
{ "_id" : ObjectId("5c77965c155eb2e753a00752"), "employee" : 3, "status" : "Inactive" }
db.events.find()
{ "_id" : ObjectId("5c77966f155eb2e753a00753"), "employee" : 3, "status" : { "new" : "Inactive", "old" : "Active" } }