Session.commitTransaction()

Definition

  • Session.commitTransaction()

New in version 4.0.

Saves the changes made by the operations in the multi-documenttransaction and ends the transaction.

Availability

  • In version 4.0, MongoDB supports multi-documenttransactions on replica sets.
  • In version 4.2, MongoDB introduces distributedtransactions, which adds support for multi-documenttransactions on sharded clusters and incorporates the existingsupport for multi-document transactions on replica sets.

Behavior

Write Concern

When commiting the transaction, the session uses the write concernspecified at the transaction start. SeeSession.startTransaction().

If you commit using "w: 1" write concern,your transaction can be rolled back during the failover process.

Atomicity

When a transaction commits, all data changes made in the transactionare saved and visible outside the transaction. That is, a transactionwill not commit some of its changes while rolling back others.

Until a transaction commits, the data changes made in thetransaction are not visible outside the transaction.

However, when a transaction writes to multiple shards, not alloutside read operations need to wait for the result of the committedtransaction to be visible across the shards. For example, if atransaction is committed and write 1 is visible on shard A but write2 is not yet visible on shard B, an outside read at read concern"local" can read the results of write 1 withoutseeing write 2.

Retryable

If the commit operation encounters an error, MongoDB drivers retry thecommit operation a single time regardless of whetherretryWrites is set to false. For more information, seeTransaction Error Handling.

Example

Consider a scenario where as changes are made to an employee’s recordin the hr database, you want to ensure that the eventscollection in the reporting database are in sync with the hrchanges. That is, you want to ensure that these writes are done as asingle transaction, such that either both operations succeed or fail.

The employees collection in the hr database has the followingdocuments:

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

The events collection in the reporting database has thefollowing documents:

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

The following example opens a transaction, updates an employee’s statusto Inactive in the employees status and inserts a correspondingdocument to the events collection, and commits the two operationsas a single transaction.

  1. // Runs the txnFunc and retries if TransientTransactionError encountered
  2.  
  3. function runTransactionWithRetry(txnFunc, session) {
  4. while (true) {
  5. try {
  6. txnFunc(session); // performs transaction
  7. break;
  8. } catch (error) {
  9. // If transient error, retry the whole transaction
  10. if ( error.hasOwnProperty("errorLabels") && error.errorLabels.includes("TransientTransactionError") ) {
  11. print("TransientTransactionError, retrying transaction ...");
  12. continue;
  13. } else {
  14. throw error;
  15. }
  16. }
  17. }
  18. }
  19.  
  20. // Retries commit if UnknownTransactionCommitResult encountered
  21.  
  22. function commitWithRetry(session) {
  23. while (true) {
  24. try {
  25. session.commitTransaction(); // Uses write concern set at transaction start.
  26. print("Transaction committed.");
  27. break;
  28. } catch (error) {
  29. // Can retry commit
  30. if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes("UnknownTransactionCommitResult") ) {
  31. print("UnknownTransactionCommitResult, retrying commit operation ...");
  32. continue;
  33. } else {
  34. print("Error during commit ...");
  35. throw error;
  36. }
  37. }
  38. }
  39. }
  40.  
  41. // Updates two collections in a transactions
  42.  
  43. function updateEmployeeInfo(session) {
  44. employeesCollection = session.getDatabase("hr").employees;
  45. eventsCollection = session.getDatabase("reporting").events;
  46.  
  47. session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );
  48.  
  49. try{
  50. employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } );
  51. eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } );
  52. } catch (error) {
  53. print("Caught exception during transaction, aborting.");
  54. session.abortTransaction();
  55. throw error;
  56. }
  57.  
  58. commitWithRetry(session);
  59. }
  60.  
  61. // Start a session.
  62. session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
  63.  
  64. try{
  65. runTransactionWithRetry(updateEmployeeInfo, session);
  66. } catch (error) {
  67. // Do something with error
  68. } finally {
  69. session.endSession();
  70. }

See also