使用虚拟时钟值

KTM 为每个事务管理器对象提供虚拟时钟。 当资源管理器调用 ZwCreateTransactionManager 时,KTM 会将对象的虚拟时钟值设置为 1。 每次开始提交操作时,KTM 都会递增虚拟时钟值。 每当 KTM 写入其日志流时,它会在日志记录中包括当前虚拟时钟值。

当资源管理器调用 ZwRecoverTransactionManager 时,KTM 会读取流到流末尾的日志流记录,并将事务管理器对象的虚拟时钟值设置为它在对象的日志流中找到的最后一个值。

当资源管理器调用 ZwRollforwardTransactionManager 时,KTM 将读取日志流记录到指定的时钟值,并将事务管理器对象的虚拟时钟值设置为指定的时钟值。

KTM 使资源管理器和上级事务管理器能够修改事务管理器对象的虚拟时钟值,但它们通常不必修改时钟值。

何时修改虚拟时钟值

通常,事务处理系统 (TPS) 不必修改虚拟时钟值,除非 TPS 中的组件尝试同步多个日志流。

例如,假设 TPS 包含多个在预准备/准备/提交序列期间相互通信的资源管理器。 此外,假设每个资源管理器创建具有唯一日志流的事务管理器对象。 为了确保 KTM 在恢复操作期间将所有资源管理器的状态还原到同一时间点,这些资源管理器可能会使用以下步骤:

  • 当一个资源管理器与另一个资源管理器通信时,它会传递从 KTM 或另一个资源管理器接收的最新虚拟时钟值。

  • 每当资源管理器调用接受虚拟时钟值的 KTM 例程 (请参阅本主题) 的以下部分时,它都会传递从 KTM 或其他资源管理器收到的最高时钟值。

  • 每个资源管理器都会将虚拟时钟值写入其日志流,并在执行回滚或恢复操作时使用这些值。

这些步骤会导致 KTM 为每个事务管理器对象存储的虚拟时钟值几乎或完全匹配。 因此,当恢复操作导致 KTM 读取其日志流,或者回滚操作导致资源管理器读取其日志流时,恢复或回滚基于同步的日志流。

如何修改虚拟时钟值

资源管理器可以通过将新值传递给 ZwPrepareComplete、ZwPrepareCompleteZwCommitCompleteZwRollbackCompleteZwReadOnlyEnlistmentZwSinglePhaseReject 来修改虚拟时钟值。

高级事务管理器可以通过将新值传递给 ZwPrepareEnlistment、ZwPrepareEnlistmentZwCommitEnlistmentZwReadOnlyEnlistment 来修改虚拟时钟值。

此外,使用 ResourceManagerNotification 回调例程的资源管理器或高级事务管理器可以修改回调例程接收的虚拟时钟值。 然后 KTM 保存更新的值。

如果资源管理器或高级事务管理器将新的时钟值传递给 KTM,则 KTM 仅在新值大于当前时钟值时才保存新值。 否则,KTM 将保留当前时钟值。

资源管理器和高级事务管理器可以通过调用 ZwQueryInformationTransactionManager 例程来获取事务管理器对象的虚拟时钟值。