温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

mongodb有没有事务

发布时间:2020-08-24 10:45:50 来源:亿速云 阅读:301 作者:Leah 栏目:编程语言

今天就跟大家聊聊有关mongodb有没有事务,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

MongoDB 4.0 引入的事务功能,支持多文档 ACID 特性,例如使用 mongo shell 进行事务操作。

> 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()回滚事务)

支持 MongoDB 4.0 的其他语言 Driver 也封装了事务相关接口,用户需要创建一个 Session,然后在 Session 上开启事务,提交事务。例如:

python 版本

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()

java 版本

try (ClientSession clientSession = client.startSession()) {
   clientSession.startTransaction();
   collection.insertOne(clientSession, docOne);
   collection.insertOne(clientSession, docTwo);
   clientSession.commitTransaction();
}

一、预备工作

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

成功后如图:

mongodb有没有事务

命令初始化

rs.initiate()

效果如图:

mongodb有没有事务

成功的结果是(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();
}

看完上述内容,你们对mongodb有没有事务有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI