zoukankan      html  css  js  c++  java
  • mongodb 事务学习总结

    mongodb 事务学习总结

     

    一、预备工作

    1.MongoDB需要4.0版本+

    2.需要自己搭建MongoDB复制集,单个mongodb server 不支持事务。

    事务原理:mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。mongodb各个节点常见的搭配方式为:一主一从、一主多从。主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

    3.搭建复制集步骤

    • 启动mongo主节点实例,bin目录下命令窗口执行,复制集命名为doudou, 8080端口的数据库文件位于db1目录下,--dbpath=路径写自己的,启动后勿关闭命令窗口
      1
      mongod --replSet doudou --dbpath=E:\mongoDb\data\db1 --port=8080  
    • 启动mongo从节点实例,bin目录下命令窗口执行,复制集命名为doudou, 8081端口的数据库文件位于db2目录下,--dbpath=路径写自己的,启动后勿关闭命令窗口
      1
      mongod --replSet doudou --dbpath=E:\mongoDb\data\db2 --port=8081
    • 两个节点启动后,bin目录下打开命令窗口,连接主节点
      1
      mongo --port=8080
    • 命令初始化
      1
      rs.initiate()
    • 两个节点启动后,bin目录下打开命令窗口,连接主节点
      1
      mongo --port=8080

        成功后如图:

        

    • 命令初始化

      1
      rs.initiate()

        效果如图:

        

        成功的结果是(ok项是1,失败是0)

        查看是否是主节点 rs.isMaster()

        查看复制集状态 rs.status()

    • 初始化配置
      1
      rs.conf()

      

    • 向主节点添加从节点
      1
      rs.add("localhost:8081")
    • 查看主节点状态
      1
      rs.status()

      复制集配置完成。

    二、复制集中的坑点

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

    1
    mongoose.connection.collection('集合名'// 注:集合名需要小写且加s,如model为Cat,集合名这里应写为cats

    2.触发Schema定义的中间件默认值需要构造model实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 解决方式
    //新增
     
    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函数
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      // 获取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
        }
    • 执行事务逻辑

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      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();
      }

        

    with client.start_session() as s:
        s.start_transaction()
        collection_one.insert_one(doc_one, session=s)
        collection_two.insert_one(doc_two, session=s)
        s.commit_transaction()
    try (ClientSession clientSession = client.startSession()) {
       clientSession.startTransaction();
       collection.insertOne(clientSession, docOne);
       collection.insertOne(clientSession, docTwo);
       clientSession.commitTransaction();
    }
     
     
    > s = db.getMongo().startSession()
    session { "id" : UUID("3bf55e90-5e88-44aa-a59e-a30f777f1d89") }
    > s.startTransaction()
    > session.getDatabase("mytest").coll01.insert({x: 1, y: 1})
    WriteResult({ "nInserted" : 1 })
    > session.getDatabase("mytest").coll02.insert({x: 1, y: 1})
    WriteResult({ "nInserted" : 1 })
    > s.commitTransaction()  (或者 s.abortTransaction()回滚事务)
  • 相关阅读:
    前端构建工具gulpjs的使用介绍及技巧(转载)
    jq checked 设置问题
    JavaScript面向对象及相关知识
    github 操作指南
    WebStorm常用快捷键
    Windows下Scala环境搭建
    For与Function进阶实战、Lazy的使用笔记总结
    第3课 Scala函数式编程彻底精通及Spark源码阅读笔记
    第2课 Scala面向对象彻底精通及Spark源码SparkContext,RDD阅读总结
    第1课 Scala入门与实战笔记总结
  • 原文地址:https://www.cnblogs.com/xiondun/p/15641175.html
Copyright © 2011-2022 走看看