探坑mongoDB4.0事務回滾的辛酸歷程

主管前幾天發現mongoDB已經升級到4.0了,火燒眉毛得讓我實現他期待已久的事務回滾,發現仍是有不少坑啊!
下面是我將已有的本地mongoDB升級到支持事務回滾的歷程,分享出來,有錯誤的地方歡迎指正!
以mac爲例哈html

部署mongodb事務回滾

1.準備工做

  • 升級mongodb至4.0.0
$ brew upgrade mongodb
  • 升級或安裝mongodb.js v3.1.0 以上
$ npm i mongodb --save-dev

  • 升級完上述後,db.js裏鏈接mongo時,
    會警告,讓你在connect的option里加一個字段
    useNewUrlParser:true
    這時若是有用戶驗證,還須要在connect的option裏再加一個字段
    authSource:用戶所在的db,通常爲admin
    不然會報驗證失敗,找不到用戶的錯誤,好比
const mongoClient = await MongoClient.connect(mongoClientUrl, {
      auth: {
        user: config.dbUserName,
        password: config.dbUserPassword,
      },
      authSource:'admin',
      useNewUrlParser:true,
    });

2.將已有的數據庫改形成複製集

目前事務回滾只能在複製集上操做,單獨的mongodb server是不能操做事務的

  • 關掉全部的mongod
  • 在平時啓動mongod的命令後添加--replSet rs0,好比
$ mongod -dbpath ./db --port 27017 --replSet rs0
  • 再開個shell,創一個不一樣端口的mongo實例,好比
$ mongod -dbpath ./db_repl --port 27018 --replSet rs0
  • 鏈接27017的mongo實例,並設置
$ mongo
$ rs.initiate()
$ rs.add('localhost:27018');
  • 完成

3.寫回滾代碼

  • 在db.js裏新增了一個方法
export const getSession = async function() {
      return await state.mongoClient.startSession();
    };
  • 每次在須要回滾的mongo代碼前調用這個方法拿到session,開始回滾的標記
const session = await db.getSession();
    session.startTransaction({
        readConcern: {level: 'snapshot'},
        writeConcern: {w: 'majority'},
    });
  • 在每次調用mongodb.js的方法操做數據庫時,都要帶上session,好比
db
    .collection(this.collecitonName)
    .insertOne(doc,{session});
  • 在你處理錯誤並以爲須要回滾了,執行
await session.abortTransaction();
  • 在你以爲沒問題,一塊兒正常結束時,執行
await session.commitTransaction();
  • 個人代碼裏可能有一些封裝的代碼沒有放上去,致使不必定能理解。我只是舉個栗子去實現,具體的代碼實現能夠看參考連接1

4.總結

  • useNewUrlParser這個屬性會在url裏識別驗證用戶所需的db,未升級前是不須要指定的,升級到必定要指定,無論是在url後面,仍是用authSource
  • 事務回滾只能在複製集上操做,我猜想實現的原理多是這樣:先記錄主節點的session,而後回滾的話,經過這個session查找副節點的數據快照,而後將這快照再應用到主節點上,實現回滾。固然,實際狀況應該至關複雜,否則mongoDB也不會用3年時間來實現這個操做。

5.參考連接

我只是個前端啊,爲何要這麼折磨我QAQ

相關文章
相關標籤/搜索