简体   繁体   中英

Is it possible one transaction for multiple connections in mongodb?

I'm trying implement one transaction for multiple database connection in mongodb. But it's stuck in startSession(). I have two db(replica set) and two connection for each one.

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;

In addition about transactions form MongoDB document:

You can specify read/write (CRUD) operations on existing collections. The collections can be in different databases ref

both your databases have to be on the same mongodb cluster for this to work. So instead of this

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

Use the mongoose Connection.useDB() method https://mongoosejs.com/docs/api/connection.html#connection_Connection-useDb . That way mongoose will use the same connection pool for both connections. Something like this:

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

Now lets say you have 2 models, model1 for db1 and model2 for db2

then you can create a transaction that can work on both the dbs something like this

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

For more info check out the NodeJS example here: https://docs.mongodb.com/manual/core/transactions-in-applications/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM