0

我知道该函数的名称似乎是不言自明的,但是,经过一段时间的研究,我在 clientSession 中的任何地方都找不到事务号。是内部号码吗?有可能得到它吗?

4

1 回答 1

0

mongodb 使用事务编号来跟踪每个会话的每个事务的操作(读/写)。startSession()每当您创建与数据库服务器的 mongodb 连接时,可以通过调用显式或隐式启动会话。

incrementTransactionNumber() 如何与会话一起工作(显式)

当您启动会话时,通过调用client.startSession() method,它将创建一个新的ClientSession. 这会将已创建的服务器会话池作为其构造函数参数之一。(请参阅)这些服务器会话有一个名为的属性,该属性txnNumber被初始化为 0。(初始化)因此,每当您通过调用启动事务时startTransaction(),客户端会话对象都会在incrementTransactionNumber()内部调用以增加txnNumber服务器会话。并且所有后续操作都将使用相同的txnNumber, 直到您调用 ,commitTransaction()abortTransaction()方法。在 clientSession 的任何地方都找不到它的原因是,它是 serverSession 而不是 clientSession 的属性。

服务器会话

class ServerSession {
  constructor() {
    this.id = { id: new Binary(uuidV4(), Binary.SUBTYPE_UUID) };
    this.lastUse = now();
    this.txnNumber = 0;
    this.isDirty = false;
  }

因此,每当您尝试向数据库发送命令(读/写)时,它txnNumber都会随之发送。(将事务编号分配给命令) 这是为了跟踪每个会话属于给定事务的数据库操作。(在每个会话中唯一标识每个事务的事务操作历史记录。)

incrementTransactionNumber() 如何处理会话(隐式)

在这种情况下,如果该命令不属于事务并且它是启用了 retryWrites 的写入操作,则每次向数据库发出新命令时都会调用它。因此,每个新的写操作都会有新的事务号,只要它不属于使用startTransaction(). 但在这种情况下,atxnNumber也会与每个命令一起发送。

执行操作

const willRetryWrite =
      topology.s.options.retryWrites === true &&
      session &&
      !inTransaction &&
      supportsRetryableWrites(server) &&
      operation.canRetryWrite;

    if (
      operation.hasAspect(Aspect.RETRYABLE) &&
      ((operation.hasAspect(Aspect.READ_OPERATION) && willRetryRead) ||
        (operation.hasAspect(Aspect.WRITE_OPERATION) && willRetryWrite))
    ) {
      if (operation.hasAspect(Aspect.WRITE_OPERATION) && willRetryWrite) {
        operation.options.willRetryWrite = true;
        session.incrementTransactionNumber();
      }

      operation.execute(server, callbackWithRetry);
      return;
    }

    operation.execute(server, callback);

也请阅读这篇文章txnNumber是的,如果您需要,您可以通过属性获取任何会话的交易号, clientSession.serverSession.txnNumber.

于 2021-03-20T08:30:08.650 回答