MongoDB transactions


From MongoDB 4.0 they introduced transactions called 'Multi-Document transactions'.

What is Transaction

In MongoDB, each and every operation or query may modify a single document or multiple documents, For example, updateOne() operation updates one document is atomic, if we try to modify multiple documents by using a single operation like updateMany() is not atomic because of multiple documents are modifying in the collection. If we want to make multiple write operations as atomic we need a transaction.

In MongoDB 4.0 Multi-Document transactions support available for atomic operation on multiple writes.

Properties of Transaction

  • When the transaction has committed all data operations on the transaction will commit automatically.
  • If any operation fails, the transaction will fail.
  • When the transaction has failed all data operations on the transaction will roll back automatically.
  • Until transaction committed no write operation data will be exposed to the outside world.

In Version 4.0, Multi-Document transactions supports transaction on replica sets.

In Version 4.2, Multi-Document transactions supports transaction on replica sets, sharded clusters .

Operation on Transaction

  • CRUD operation is allowed in a transaction.
  • Write to a capped collection is also allowed.
  • Write to system.* collections.
  • For cursors created outside of a transaction, we can not use it inside of a transaction.
  • For cursors created inside of a transaction, we can use in outside of a transaction also.

Example of transaction in mongo shell

// Prereq: Create collections. CRUD operations in transactions must be on existing collections.
db.getCollection('users').insert( {'userName': "Foo"}, { writeConcern: { w: "majority", wtimeout: 2000 } } );
db.getCollection('roles').insert( {'roleName':"Admin"}, { writeConcern: { w: "majority", wtimeout: 2000 } } );

// Start a session.
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );

coll1 = session.db.getCollection('users');
coll2 = db.getCollection('roles');

// Start a transaction
session.startTransaction( { readConcern: { level: "local" }, writeConcern: { w: "majority" } } );

// Operations inside the transaction
try {
   coll1.insertOne( { 'userName': "Foo"} );
   coll2.insertOne( { 'roleName':"Admin" } );
} catch (error) {
   // Abort transaction on error
   session.abortTransaction();
   throw error;
}

// Commit the transaction using write concern set at transaction start
session.commitTransaction();

session.endSession();