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