恢复处理

发生任何中断正常事务处理的故障后,KTM 和每个资源管理器都必须执行 恢复 操作。 恢复是事务参与者到达每个事务状态的一致视图的过程。

资源管理器可能对事务的结果 持怀疑态度 ,这意味着在发生故障时,他们已收到TRANSACTION_NOTIFY_PREPARE通知,已准备好持久存储,但尚未收到 (或接收,但未记录) 事务的最终结果。 同样,如果事务已准备好,但尚未收到 (或接收,但未记录) 结果,KTM 可能会怀疑该事务。 在恢复时,必须重新发送已发送但未确认的所有结果。 例如,如果资源管理器收到TRANSACTION_NOTIFY_COMMIT通知并调用了 CommitComplete 函数,则 RM 在恢复时仍可能收到重复TRANSACTION_NOTIFY_COMMIT通知。

若要使事务在资源管理器或系统故障后正确恢复,每个资源管理器必须在每次启动时执行以下操作:

  1. 调用 OpenResourceManager 函数以使用其唯一的持久名称重新打开其资源管理器句柄。 这会通知 KTM 资源管理器再次运行,并可用于执行恢复。 如果不存在要恢复的登记,则对 OpenResourceManager 的调用可能会失败。 调用 CreateResourceManager 以重新创建 RM 对象。

  2. 调用 RecoverResourceManager。 资源管理器将为每个需要执行恢复操作的登记接收 TRANSACTION_NOTIFY_RECOVER 通知事件,然后是TRANSACTION_NOTIFY_LAST_RECOVER。 通知事件包括事务和登记的全局唯一标识符。

  3. 调用 OpenEnlistment 函数以重新打开资源管理器收到TRANSACTION_NOTIFY_RECOVER通知的每个登记句柄。

  4. 对于 OpenEnlistment 打开的每个登记,调用 RecoverEnlistment。 这会导致重新传送TRANSACTION_NOTIFY_COMMIT或TRANSACTION_NOTIFY_INDOUBT通知。

  5. 如果 RM 接收TRANSACTION_NOTIFY_COMMIT,则 RM 可以通过调用 CommitComplete 来完成事务。

    如果 RM 收到TRANSACTION_NOTIFY_INDOUBT,则 RM 应等待结果通知到达。

  6. 对于 RM 未收到TRANSACTION_NOTIFY_RECOVER通知但以前收到TRANSACTION_NOTIFY_PREPARE通知的任何事务,RM 应像回滚事务一样处理该事务。

注意

在执行恢复过程中,允许资源管理器登记或创建新事务。

 

KTM 使用 假定的中止 事务模型。 以下方案演示了此行为。 假设 KTM 和资源管理器位于同一台计算机上。 假设 KTM 为事务发出准备通知,但在 KTM 记录准备通知之前系统崩溃。 进一步假设资源管理器在系统崩溃之前接收并记录准备通知。 还原系统后,KTM 不知道事务,因为它从未记录准备阶段。 资源管理器了解事务,因为它接收、处理和记录了准备通知。 当 KTM 发出恢复通知时,资源管理器不包含有关事务的恢复通知。 使用假定中止模型时,在这种情况下,资源管理器在未收到通知以对该事务执行恢复时,会将准备的事务视为中止。