补偿日志的重做信息对应于日志条目的撤消信息,这使得在撤消阶段必须创建它们。
在我看来,CLR 重做信息与触发它们的日志的撤消信息相同。
但是不应该是他们有REDO信息以便在中断恢复过程的情况下取消执行的UNDO操作吗?
这是一个例子:
让 T2 成为失败交易:
<#55, T2, P3, J=J+9, J = J-9, #53>
J=J+9 是重做操作,J = J-9 是撤消操作。
现在,在重做阶段附加到日志文件的 CLR 将是:
<#56, T2, J=J-9,__, #53>
J=J-9 是原始日志条目的撤消操作,作为 CLR 中的重做信息。如果恢复中断,日志条目#56 将在重做阶段执行。
CLR 的目的是确保重新启动恢复过程并再次运行它总是会导致相同的结果。在重新运行的重做阶段运行 J=J-9 操作如何确保这一点?
有人可以向我解释一下吗?
补偿日志记录 (CLR) 在正常操作期间不会写入日志。它们是在处理回滚时产生的,无论是应用程序请求还是由于崩溃。由于它们的唯一用途是在回滚期间,它们只需要保存足够的信息来执行该操作,即示例中的 J=J-9。每个 CLR 通过 LSN 引用与其对应的原始日志记录配对。
恢复的重做阶段的目的是将数据库恢复到崩溃时的状态。如果崩溃发生在恢复的中途,那么第二次恢复的重做阶段应该在第一次恢复的中途离开数据库。第二次恢复的重做阶段处理由第一次恢复的撤消阶段写入的 CLR。由于 CLR 链接到原始更新日志记录,知道最后处理的 CLR 会告诉第二个恢复的撤消阶段要跳转到哪个日志记录,以便它可以完成回滚。
使用给定的示例,第一个恢复的撤消阶段将处理日志记录 #55 的撤消操作 (J = J-9) 并创建 CLR #56。然后它将返回到上一个链接记录(#53)。假设我们在处理之前崩溃了。第二次恢复的重做阶段将处理 CLR #56 的操作。如果这是最后一个 CLR,则第二次恢复的撤消阶段将沿着链接返回到 #53 并从那里完成回滚。在第二次和后续恢复期间,#56 有效地替换了#55。
那么为什么要为这一切烦恼呢?为什么第二次恢复不能完全按照第一次恢复的方式进行?因为 Aries 假定缓冲区管理器使用窃取,没有强制策略。在第一次恢复期间,页面可能已部分回滚,然后从缓冲池中换出。因此,第二次恢复不是从第一次恢复的相同持久状态开始,因此它不能简单地第二次执行相同的操作。