mongodb 事務學習總結


一、預備工作

1.MongoDB需要4.0版本+

2.需要自己搭建MongoDB復制集,單個mongodb server 不支持事務。

事務原理:mongodb的復制至少需要兩個節點。其中一個是主節點,負責處理客戶端請求,其余的都是從節點,負責復制主節點上的數據。mongodb各個節點常見的搭配方式為:一主一從、一主多從。主節點記錄在其上的所有操作oplog,從節點定期輪詢主節點獲取這些操作,然后對自己的數據副本執行這些操作,從而保證從節點的數據與主節點一致。

3.搭建復制集步驟

  • 啟動mongo主節點實例,bin目錄下命令窗口執行,復制集命名為doudou, 8080端口的數據庫文件位於db1目錄下,--dbpath=路徑寫自己的,啟動后勿關閉命令窗口
    mongod --replSet doudou --dbpath=E:\mongoDb\data\db1 --port=8080  
  • 啟動mongo從節點實例,bin目錄下命令窗口執行,復制集命名為doudou, 8081端口的數據庫文件位於db2目錄下,--dbpath=路徑寫自己的,啟動后勿關閉命令窗口
    mongod --replSet doudou --dbpath=E:\mongoDb\data\db2 --port=8081
  • 兩個節點啟動后,bin目錄下打開命令窗口,連接主節點
    mongo --port=8080
  • 命令初始化
    rs.initiate()
    
  • 兩個節點啟動后,bin目錄下打開命令窗口,連接主節點
    mongo --port=8080
    

 

    成功后如圖:

    

 

  • 命令初始化

    rs.initiate()
    

    效果如圖:

    

    成功的結果是(ok項是1,失敗是0)

    查看是否是主節點 rs.isMaster()

    查看復制集狀態 rs.status()

  • 初始化配置
    rs.conf()

  

  • 向主節點添加從節點
    rs.add("localhost:8081")
  • 查看主節點狀態
    rs.status()
    

    復制集配置完成。

二、復制集中的坑點

1.需使用mongoose.connection對集合進行事務操作,其他model的CRUD方法不支持事務

mongoose.connection.collection('集合名') // 注:集合名需要小寫且加s,如model為Cat,集合名這里應寫為cats

2.觸發Schema定義的中間件默認值需要構造model實例

const CatSchema = new Schema({
    name: {
        type: String
        default: 'cat'
    },
    created: {
     type: Date,
     default: Date.now
  }
})

const Cat = mongoose.model('Cat', CatSchema)

new Cat() // 觸發中間件

  

 3.insertOne,findOneAndUpdate等方法對數據的新增,需上面第二點進行依賴,否則直接insertOne 插入一條數據,定義的默認值不會觸發,如created字段,chema內部定義的type: Schema.ObjectId的相應字段,insertOne插入后都會變成字符串類型,不是Schema.ObjectId類型

// 解決方式
//新增

const Cat= new Cat();
const data = {name: 5}
for (let key in data) {
      Cat[key] = data[key];
    }
db.collection('cats').insertOne(Cat);

// 查詢修改

db.collection('cats')
.findOneAndUpdate({_id: mongoose.Types.ObjectId(你的id)}, {$set: {name: 修改值}})

  

三、開始事務

注:以下皆為egg實例代碼

  • 封裝獲取session函數
    // 獲取session,回滾事務
      async getSession(opt = {
        readConcern: { level: "snapshot" },
        writeConcern: { w: "majority" }
      }) {
        const { mongoose } = this.app
        const session = await mongoose.startSession(opt);
        await session.startTransaction();
        return session
      }
    

     

  • 執行事務邏輯

        const { mongoose } = this.ctx.app;
        const session = await this.ctx.getSession();
        const db = mongoose.connection;
        try {
          const data = this.ctx.request.body;
          const Cat = new this.ctx.model.Cat();
          for (let key in data) {
            Cat[key] = data[key]
          }
          await db
            .collection('cats')
            .insertOne(Cat, { session });
          // 提交事務
          await session.commitTransaction();
          this.ctx.end();
        } catch (err) {
          // 回滾事務
          await session.abortTransaction();
          this.ctx.logger.error(new Error(err));
        } finally {
          await session.endSession();
        }
    

      

 

  以上就是思考總結,完畢


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM