乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      【Mongodb】事務

       新進小設計 2022-03-30

       

      概述

      • Mongodb 4.0 支持副本集的多文檔事務
      • Mongodb 4.2 支持分片集群的多文檔事務

      單個Server是不支持使用事務,所以要學習事務,需要搭建一個副本集/分片集群

      另外需要說明是,單個文檔操作是原子操作,而mongodb是文檔型數(shù)據(jù)庫,在單個文檔上,可以嵌入對象/數(shù)組這種格式來維護數(shù)據(jù)的關(guān)系,而不應該使用多個集合來維護數(shù)據(jù)之間的關(guān)系。由于mongodb的這種特性,所以單個文檔操作消除了很多需要事務的需求。

       

      搭建副本集

      下面以最簡單的方式搭建一個副本集

      1.  啟動多個mongod實例,這里使用cmd命令啟動

      start "Mongodb Service - 27017" /min mongod --port 27017 --replSet "rs0" --dbpath "F:\Database\Mongodb\Data27017" --logpath "F:\Database\Mongodb\Log\mongod.27017.log"
      start "Mongodb Service - 27018" /min mongod --port 27018 --replSet "rs0" --dbpath "F:\Database\Mongodb\Data27018" --logpath "F:\Database\Mongodb\Log\mongod.27018.log"

      參數(shù)說明

      • replSet : 設置副本集名稱
      • port : 設置端口,因為我是單機,所以只能設置不同端口
      • dbpath: 數(shù)據(jù)文件路徑,注:文件夾必須是存在,mongod不會自動創(chuàng)建
      • logpath: 日志文件名稱,這個不需要提前新建,若不存在mongod會自動創(chuàng)建

      2.  連接任意一個實例,這里就選擇27017這個默認端口

      mongo

       

      3. 啟動副本集

      rs.initiate({
          _id: "rs0",
          members: [
              { _id: 0, host: "127.0.0.1:27017" },
              { _id: 1, host: "127.0.0.1:27018" }
          ]
      })

      參數(shù)說明

      • _id : 副本集名稱,就是啟動實例時指定那個名稱
      • members : 這個就是所有成員,_id每個成員的標識,整數(shù)型[0,255]

      返回字段"ok" : 1 代表創(chuàng)建成功

      rs.initiate({}),這里除了幾個必須的,都是使用默認配置去啟動,更多配置參數(shù)可以參考replica-configuration

       

      4. 查看當前配置信息

      rs.conf()

       

      5. 查看副本集信息

      rs.status()

       

      到這,副本集就搭建完成

       

      事務

      1. 連接副本集

      mongo mongodb://127.0.0.1:27017,127.0.0.1:27018/?replicaSet=rs0

      可以直接連接主副本的實例,也可以用這種url形式可以自動連接主副本(推薦使用后者)

       

      2. 準備2條數(shù)據(jù)

      db.balance.insert({ name: "Wilson", balance: 100 }, { writeConcern: { w: "majority", wtimeout: 2000 } });
      db.record.insert({ name: "Wilson", change: 100, balance: 100, }, { writeConcern: { w: "majority", wtimeout: 2000 } });

       

      測試正常提交

      模擬一個扣錢動作,其中扣款和流水在一個事務里

      session = db.getMongo().startSession({ readPreference: { mode: "primary" } });
      balanceCol = session.getDatabase("mongo").balance;
      recordCol = session.getDatabase("mongo").record;
      session.startTransaction({ readConcern: { level: "local" }, writeConcern: { w: "majority" } });
      
      try {
          balanceCol.updateOne({ "name": "Wilson" }, { $set: { "balance": 50 } });
          recordCol.insertOne({ "name": "Wilson", change: -50, balance: 50 });
      } catch (error) {
          session.abortTransaction();
      } 
      session.commitTransaction();
      session.endSession();

       

      查看余額情況

      db.balance.aggregate([
          { $lookup: { from: "record", localField: "name", foreignField: "name", as: "changs" } },
          { $project: { "_id": 0, "changs._id": 0, "changs.name": 0 } },
      ]);

      結(jié)果,可以看到余額扣了,多了一條流水

      { "name" : "Wilson", "balance" : 50, "changs" : [ { "change" : 100, "balance" : 100 }, { "change" : -50, "balance" : 50 } ] }

       

       

      測試失敗回滾

      事務內(nèi)多增加一個插入不存在的集合操作,讓事務報錯

      session.startTransaction({ readConcern: { level: "local" }, writeConcern: { w: "majority" } });
      try {
          balanceCol.updateOne({ "name": "Wilson" }, { $set: { "balance": -50 } });
          recordCol.insertOne({ "name": "Wilson", change: -50, balance: 0 });
          session.getDatabase("mongo").user.insert({ "time": new Date() });    //多增加操作一個不存在的表
      } catch (error) {
          session.abortTransaction();
          throw error;
      }
      session.commitTransaction();
      session.endSession();

       

      返回報錯信息,顯示事務被中斷了

      2020-04-15T21:37:05.576+0800 E  QUERY    [js] uncaught exception: Error: command failed: {
              "errorLabels" : [
                      "TransientTransactionError"
              ],
              "operationTime" : Timestamp(1586957825, 1),
              "ok" : 0,
              "errmsg" : "Transaction 0 has been aborted.",
              "code" : 251,
              "codeName" : "NoSuchTransaction",
              "$clusterTime" : {
                      "clusterTime" : Timestamp(1586957825, 1),
                      "signature" : {
                              "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                              "keyId" : NumberLong(0)
                      }
              }
      } :
      _getErrorWithCode@src/mongo/shell/utils.js:25:13
      doassert@src/mongo/shell/assert.js:18:14
      _assertCommandWorked@src/mongo/shell/assert.js:583:17
      assert.commandWorked@src/mongo/shell/assert.js:673:16
      commitTransaction@src/mongo/shell/session.js:971:17
      @(shell):1:1
      
      

      再查看當前余額情況

      db.balance.aggregate([
          { $lookup: { from: "record", localField: "name", foreignField: "name", as: "changs" } },
          { $project: { "_id": 0, "changs._id": 0, "changs.name": 0 } },
      ]);

      可以看到,余額和流水都沒變化。

      { "name" : "Wilson", "balance" : 50, "changs" : [ { "change" : 100, "balance" : 100 }, { "change" : -50, "balance" : 50 } ] }

       

       參考文章


      Replication — MongoDB Manual

      Transactions — MongoDB Manual

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多