mongodb我是否需要在commitTransaction失败后需要abortTransaction

时间:2018-08-30 06:50:57

标签: mongodb mongoose transactions commit rollback

mongoose / mongodb node.js代码:

session.commitTransaction(function(err, reply){
    if(err) {
       session.abortTransaction(); //Do I need this abort?
    }
}

有人可以帮助我吗?

2 个答案:

答案 0 :(得分:1)

查看mongodb的documentation有关交易及其提供的示例。

在数据库请求发生异常之后,您应该使用session.abortTransaction();

但是在commit拒绝之后不需要。


mongoose没有abortTransactions()。所以我想这不是必需的。


// Runs the txnFunc and retries if TransientTransactionError encountered

function runTransactionWithRetry(txnFunc, session) {
    while (true) {
        try {
            txnFunc(session);  // performs transaction
            break;
        } catch (error) {
            // If transient error, retry the whole transaction
            if ( error.hasOwnProperty("errorLabels") && error.errorLabels.includes("TransientTransactionError")  ) {
                print("TransientTransactionError, retrying transaction ...");
                continue;
            } else {
                throw error;
            }
        }
    }
}

// Retries commit if UnknownTransactionCommitResult encountered

function commitWithRetry(session) {
    while (true) {
        try {
            session.commitTransaction(); // Uses write concern set at transaction start.
            print("Transaction committed.");
            break;
        } catch (error) {
            // Can retry commit
            if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes("UnknownTransactionCommitResult") ) {
                print("UnknownTransactionCommitResult, retrying commit operation ...");
                continue;
            } else {
                print("Error during commit ...");
                throw error;
            }
       }
    }
}

// Performs inserts and count in a transaction
function updateEmployeeInfo(session) {
   employeesCollection = session.getDatabase("hr").employees;
   eventsCollection = session.getDatabase("reporting").events;

   // Start a transaction for the session that uses:
   // - read concern "snapshot"
   // - write concern "majority"

   session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );

   try{
      eventsCollection.insertOne(
         { employee: 3, status: { new: "Active", old: null },  department: { new: "XYZ", old: null } }
      );

      // Count number of events for employee 3

      var countDoc = eventsCollection.aggregate( [ { $match:  { employee: 3 } }, { $count: "eventCounts" } ] ).next();

      print( "events count (in active transaction): " + countDoc.eventCounts );

      // The following operations should fail as an employee ``3`` already exist in employees collection
      employeesCollection.insertOne(
         { employee: 3, name: { title: "Miss", name: "Terri Bachs" }, status: "Active", department: "XYZ" }
      );
   } catch (error) {
      print("Caught exception during transaction, aborting.");
      session.abortTransaction();
      throw error;
   }

   commitWithRetry(session);

} // End of updateEmployeeInfo function

// Start a session.
session = db.getMongo().startSession( { mode: "primary" } );

try{
   runTransactionWithRetry(updateEmployeeInfo, session);
} catch (error) {
   // Do something with error
} finally {
   session.endSession();
}

答案 1 :(得分:0)

旧线程,但被认为可以为新手提供一些见识。

在MongoDB的Retry transaction and commit operation example上,他们在session.abortTransaction()之后呼叫session.commitTransaction()

try {
    await commitWithRetry(session);
} catch (error) {
    await session.abortTransaction();
    throw error;
}

哪个与MongoDB的abortTransaction specification冲突,该声明如下:

  

仅当会话在会话中时才调用abortTransaction   “开始交易”或“正在进行的交易”状态。

     

如果此会话处于“事务已提交”状态,则驱动程序   必须引发包含错误消息“无法呼叫   调用commitTransaction后终止”。

     

当会话处于“开始交易”状态时,表示否   已对此交易执行操作,驱动程序不得   运行abortTransaction命令。

所以我想您的问题的答案是,您不应该。否则,您将得到错误:Cannot call abortTransaction after calling commitTransaction

相关问题