Transaction Management in MongoDB

Transaction Management in MongoDB

As I am using MongoDB since last 3 years in many environment and for many applications which is ranging from small application to enterprise application. This is my one of favourite database due to it's NOSQL nature, it's performance and simplicity in writing query.

Mainly since all my experiences I faced two main problems with MongoDB

1) Design an schema for application -

This is challenge for me because as my basic learning and mostly I developed application using RDBMS. So in nutshell my mind drive me to correlate each schema design like RDBMS, primary key, foreign key & Joins. Which is really create mess. So now before design schema I always create picture like I have to create only one document for all forms and then I start decouple it. I am trying many permutation & combination of possibilities to finalise my design which I will cover into next article.

2) Transaction Management

Simple principle of transaction management is "do-all-or-nothing".

Before the MongoDB 4.0, It's too much difficult and clumsy way to manage transactions because no inbuilt support provided for commit or rollback. MongoDB 4.0 released feature of Transaction Management to just save developers from this overhead.

MongoDB 4.0 adds support for multi-document ACID transactions, making it the only open source database to combine the speed, flexibility, and power of the document model with ACID guarantees. Through snapshot isolation, transactions provide a consistent view of data, and enforce all-or-nothing execution to maintain data integrity. Starting in version 4.0, MongoDB provides the ability to perform multi-document transactions against replica sets. With multi-document transactions, until a transaction commits, no write operations in the transaction are visible outside the transaction. That is, the multi-document transactions are atomic.

Feature Compatibility

MongoDB 4.0 or greater

Transactions & MongoDB Drivers

Clients require MongoDB drivers updated for MongoDB 4.0.

  • Java 3.8.0
  • Python 3.7.0
  • C 1.11.0
  • C# 2.7
  • Node 3.1.0
  • Ruby 2.6.0
  • Perl 2.0.0
  • PHPC 1.5.0
  • Scala 2.4.0

How to use that?

I am just showing here which will help you to implement this in 3 different technologies.

1) Shell Method

session = db.getMongo().startSession();//start session
session.startTransaction();//start session


//transaction1
session.getDatabase("test").student.insert({"name" : "Pankaj saboo"});

//transaction2
session.getDatabase("test").student.insert({"name" : "Neeraj Vishwakarma"});

After running above block if you check "student" collection of "test" database you will not find the record.

To commit above initiated transaction use following statement

session.commitTransaction()

To Rollback above initiated transactions use following statement

session.abortTransaction()

 The pending uncommitted changes are only visible inside the session context (the session which has started the transaction) and are not visible outside. )

2) In Java

try {
   ClientSession clientSession = client.startSession();
   clientSession.startTransaction();
   collection.insertOne(clientSession, docOne);
   collection.insertOne(clientSession, docTwo);
   clientSession.commitTransaction();
} catch(Exception e){
   //Abort / Rollback transaction
   clientSession.abortTransaction();
}

3) In NodeJS

const { MongoClient } = require('mongodb');
const uri = 'mongodb://localhost:27017,localhost:27018,localhost:27019/test';
const client = await MongoClient.connect(uri, { useNewUrlParser: true, replicaSet: 'rs' });

const db = client.db();

async function transaction(from, to, amount) {
  const session = client.startSession();
  session.startTransaction({
    readConcern: { level: 'snapshot' },
    writeConcern: { w: 'majority' }
  });


  try {
    const test1Collection = client.db('test1').collection('employees');
    const test2Collection = client.db('test2').collection('events');

    //transaction 1
    await test1Collection.updateOne({ employee: 3 },{ $set: { status: 'Inactive' } },
          { session });

    //transaction 2
    await test2Collection.insertOne({employee: 3,status: { new: 'Inactive', old: 'Active' }
          },{ session });

    await session.commitTransaction();
    session.endSession();
  } catch (error) {
    // If an error occurred, abort the whole transaction and// undo any changes that might have happenedawait session.abortTransaction();await session.abortTransaction();
    session.endSession();
    throw error; // Rethrow so calling function sees error
  }
}

If while performing multiple actions if transaction conflict occurs MongoDB catches the conflict and return the error on the insert (even before the commit).

Olatunji Ajayi

Software Engineer, Backend Engineer

4 年

thank you for this.

Amir Alamian

Back End Developer

4 年

I've recently used transactions in my projects and find it awesome

Omid S.

Research Assistant @ Statistical Machine Learning Lab

4 年

Thanks for this useful article.

Sachin Jindal

Senior Software Engineer at Intuit

5 年

Really helpful article! Would you please elaborate me how transaction were managed before mongodb4.0

Justin Pretorius

Frontend Developer | Angular | Typescript

5 年

Gosh would have been nice if commitTransaction could be commitTransaction({ closeSession: true }) but its a small price to pay

要查看或添加评论,请登录

Pankaj Saboo的更多文章

  • Why Google protobuf?

    Why Google protobuf?

    After reading of first google protobuf article, I received few queries like why and when to use Google protobuf?…

    1 条评论
  • Cross-platform use of Google Protobuf

    Cross-platform use of Google Protobuf

    Recently got chance to work with Google protocol Buffer(mostly called as Google Protobuf). This is an one of the simple…

    2 条评论

社区洞察

其他会员也浏览了