mongodb中的多个连接是否可能有一个事务?

时间:2019-05-06 14:36:27

标签: node.js mongodb mongoose transactions

我正在尝试为mongodb中的多个数据库连接实现一个事务。但这卡在startSession()中。我有两个db(副本集),每个都有两个连接。

var express = require('express');
var router = express.Router();
const mongoose = require('mongoose');

//set replica set
const options = { replicaSet: 'replocal', useNewUrlParser: true, };

// create connection from diffrent db
var conn = mongoose.createConnection('mongodb://localhost:27017/db1', options);
var conn2 = mongoose.createConnection('mongodb://localhost:27017/db2', options);

// create account in diffent db
const AccountFromdb1 = conn.model('AccountFromdb1', new mongoose.Schema({ name: String, balance: Number }));
const AccountFromdb2 = conn2.model('AccountFromdb2', new mongoose.Schema({ name: String, balance: Number }));

/* transaction test */
router.get('/transaction', async function (req, res, next) {


  // Insert accounts and transfer some money
  await AccountFromdb1.create({ name: 'A', balance: 5 });
  await AccountFromdb2.create({ name: 'B', balance: 10 });

  //start session
  const session = await mongoose.startSession(); // <--- stuck here
  session.startTransaction();

  try {

    const opts = { session, new: true };

    const A = await AccountFromdb1.
      findOneAndUpdate({ name: 'A' }, { $inc: { balance: -5 } }, opts);

    if (A.balance < 0) {
      throw new Error('Insufficient funds: ' + (A.balance + 5));
    }

    await AccountFromdb2.
      findOneAndUpdate({ name: 'B' }, { $inc: { balance: 5 } }, opts);

    await session.commitTransaction();
    session.endSession();
    next();

  } catch (error) {
    // If an error occurred, abort the whole transaction.
    await session.abortTransaction();
    session.endSession();
    throw error;
  }

});

module.exports = router;

关于MongoDB文档形式的交易:

  

您可以在现有集合上指定读/写(CRUD)操作。   集合可以位于不同的数据库ref

1 个答案:

答案 0 :(得分:1)

两个数据库都必须位于同一mongodb群集上,才能正常工作。所以代替这个

var conn = mongoose.createConnection('mongodb://localhost:27017/db1', options);
var conn2 = mongoose.createConnection('mongodb://localhost:27017/db2', options);

使用猫鼬Connection.useDB()方法https://mongoosejs.com/docs/api/connection.html#connection_Connection-useDb。这样,猫鼬将为两个连接使用相同的连接池。像这样:

let con1 = mongoose.createConnection('mongodb://localhost:27017/db1', options);
let con2 = con1.useDb("db2")

现在假设您有2个模型,其中db1的模型1和db2的模型2

然后您可以创建一个可以在两个数据库上工作的事务,像这样

let session =  await con1.startSession()
session.startTransaction();

try {
  // First db
  let result1 = await new Model1({...something}).save()
  // Second db
  let result2 = await new Model2({...something}).save()

  await session.commitTransaction()

} catch (err) {
  await session.abortTransaction()
  throw err
}finally {
  session.endSession();
}

有关更多信息,请在此处查看NodeJS示例:https://docs.mongodb.com/manual/core/transactions-in-applications/