An Exploration of the poignant history of mongoDB 4.0 Transaction rollback

  • 2020-08-22 22:59:57
  • OfStack

preface

The supervisor found out a few days ago that mongoDB had been upgraded to 4.0, and he couldn't wait to let me achieve the long-awaited transaction rollback. He found that there were still a lot of holes.

Here is how I upgraded my existing local mongoDB to support transaction rollback, share it out, please correct any mistakes!

Take mac, for example

Deploy mongodb transaction rollback

1. Preparation

Upgrade mongodb to 4.0.0


$ brew upgrade mongodb

Upgrade or install ES26en.js v3.1.0 or above


$ npm i mongodb --save-dev

pit

After upgrading above, when connecting mongo in ES36en. js,

It warns you to add one field to connect's option

useNewUrlParser:true .

If you have user authentication, you need to add another field to option for connect

authSource: db where the user is, 1 generally admin

Otherwise, validation fails and no user error is found, such as


 const mongoClient = await MongoClient.connect(mongoClientUrl, {
  auth: {
  user: config.dbUserName,
  password: config.dbUserPassword,
  },
  authSource:'admin',
  useNewUrlParser:true,
 });

2. Transform an existing database into a replication set

Currently, transaction rollback can only operate on replicated sets; mongodb server alone cannot operate on transactions

Turn off all mongod

Add -replSet rs0 after normally starting mongod command, for example


$ mongod -dbpath ./db --port 27017 --replSet rs0

Open another shell and create an instance of mongo with a different port, for example


$ mongod -dbpath ./db_repl --port 27018 --replSet rs0

Connect to the mongo instance of 27017 and set


$ mongo
$ rs.initiate()
$ rs.add('localhost:27018');

complete

3. Write rollback code

A new method has been added to ES101en.js


 export const getSession = async function() {
  return await state.mongoClient.startSession();
 };

Call this method each time before the mongo code needs to be rolled back to get the session flag to start rolling back


 const session = await db.getSession();
 session.startTransaction({
  readConcern: {level: 'snapshot'},
  writeConcern: {w: 'majority'},
 });

Each time the method mongodb.js is called to manipulate the database, take session with you, for example


 db
 .collection(this.collecitonName)
 .insertOne(doc,{session});

After you handle the error and feel the need to roll back, execute


await session.abortTransaction();

When you feel ok, start 1 and finish normally, execute


$ npm i mongodb --save-dev
0

There may be some encapsulated code in my code that has not been put up, which may not be understood. I just cite a chestnut to implement, specific code implementation can see reference link 1

4. To summarize

The useNewUrlParser attribute identifies the db required to authenticate the user in url and does not need to be specified before upgrading to 1, either after url or with authSource

A transaction rollback can only operate on a replicated set, and I guess the principle is this: first record the session of the primary node, and then roll back, find a snapshot of the data of the secondary node through this session, and then apply this snapshot to the primary node to achieve rollback. Of course, the actual situation should be quite complicated, otherwise mongoDB would not have taken 3 years to implement this operation.

5. Reference links

Official introduction of mongoDB mongoDB Chinese Community about replSet If you don't want step 2, run-ES154en can simply create a new mongoDB copy set for you

conclusion


Related articles: