如何重试 MongoDB 事务?

4
我有两个不同的API端点可更新集合中的相同字段(用户集合的钱包字段)。在这两个API中,事务是使用mongoose实现的。当我同时访问这两个端点时,其中一个端点成功执行,而另一个端点会出现“WriteConflict”错误,并标记为“TransientTransactionError”。
根据MongoDB文档,它提供了处理“TransientTransactionError”错误的事务重试功能。所以,请建议如何在出现这种错误时重试事务。
当我同时使用不同端点更新同一文档时,就会收到此错误。
MongoError: WriteConflict
    at Connection.<anonymous> (/Users/node_modules/mongodb-core/lib/connection/pool.js:443:61)
    at Connection.emit (events.js:196:13)
    at Connection.EventEmitter.emit (domain.js:471:20)
    at processMessage (/Users/node_modules/mongodb-core/lib/connection/connection.js:364:10)
    at TLSSocket.<anonymous> (/Users/node_modules/mongodb-core/lib/connection/connection.js:533:15)
    at TLSSocket.emit (events.js:196:13)
    at TLSSocket.EventEmitter.emit (domain.js:471:20)
    at addChunk (_stream_readable.js:290:12)
    at readableAddChunk (_stream_readable.js:271:11)
    at TLSSocket.Readable.push (_stream_readable.js:226:10)
    at TLSWrap.onStreamRead (internal/stream_base_commons.js:166:17) {
  errorLabels: [ 'TransientTransactionError' ],
  operationTime: Timestamp { _bsontype: 'Timestamp', low_: 2, high_: 1591772061 },
  ok: 0,
  errmsg: 'WriteConflict',
  code: 112,
  codeName: 'WriteConflict',
  '$clusterTime': {
    clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 2, high_: 1591772061 },
    signature: { hash: [Binary], keyId: [Long] }
  },
  name: 'MongoError',
  [Symbol(mongoErrorContextSymbol)]: {}
}

提前感谢

2个回答

3

文档提供示例展示如何正确使用事务。点击 "nodejs" 查看 node 示例。

驱动程序中的withTransaction函数实现了重试功能。


-1
您可以编写一个函数,在提交时出现错误时进行重试事务:
const commitWithRetry = async (session) => {
  for (;;) {
    try {
      await session.commitTransaction();
      session.endSession();
      break;
    } catch (error) {
      const isTransientError = Object.prototype.hasOwnProperty.call(error, 'errorLabels')
          && error.errorLabels.includes('UnknownTransactionCommitResult');
      if (!isTransientError) {
        throw error;
      }
    }
  }
};

要进行带重试的提交,请在会话对象上调用该函数:
await commitWithRetry(session);

希望这能有所帮助。 编辑: 我不知道为什么这个答案被投了反对票,但是为了提供更多的上下文,可以在MongoDB文档这里中找到这种方法的使用示例。

你只复制了完整事务管理代码的一部分,而且该文档页面上提供的代码早于修订后的事务 API(https://github.com/mongodb/specifications/blob/master/source/transactions-convenient-api/transactions-convenient-api.rst#clientsession-withtransaction)。因此,在最好的情况下,这个解决方案只能覆盖数据库/应用程序遇到的部分错误。 - D. SM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接