如果存在重做(WAL),为什么需要undo日志?



如果有可用的WAL(重做)日志,那么它将允许我们将记录持久化到磁盘并提交事务,而无需首先更新数据结构。

既然你总是可以在崩溃或失败时重新应用重做日志并更新数据结构,为什么我们仍然需要撤销日志?

我对这个问题的理解是我们仍然需要undo log,因为:

  1. 如果我们在将记录提交并持久化到磁盘之前更新了数据结构,那么我们可能需要在事务回滚时撤销数据结构中的更改。但是,我不明白为什么我们不能在更新数据结构之前等待事务提交?这听起来比维护一个撤销日志要简单。
  2. 快照隔离。MVCC要求数据结构能够访问旧版本的操作系统记录。有了撤销日志,就可以回到过去。没有撤销的记录不能提供回溯功能。

我的理解是正确的,为什么我们需要撤销日志,即使重做日志存在?

假设提交比回滚发生得更频繁。也就是说,如果客户端不希望更新被提交,他们就不会执行更新。回滚是例外。

当您执行更改时,更改将被写入数据页,而旧版本的页面将被写入undo日志。更改还被写入重做日志以进行崩溃恢复。在提交时,唯一需要发生的事情就是新版本现在被认为已提交。至少在其他并发事务不再需要它作为MVCC快照时,可以计划将undo日志中的副本作为垃圾丢弃。事实上,为了满足不同的快照,undo日志中可能有给定行的多个版本。

如果没有撤销日志,一切都依赖于重做日志,那么结果将是:

  • 执行更改将只写入重做日志。这是在查询执行期间的轻微加速。
  • 但是commit将被迫做更多的工作。基本上,这相当于在崩溃恢复期间所做的工作,将重做日志条目与现有页面进行协调,并重建"当前"页。
  • 重做日志调和不能发生,直到所有其他并发可读事务完成,因为他们仍然需要查看数据页中的旧版本的数据。这将是一个问题,因为重做日志有一个固定的大小;一个未完成的事务可能会导致重做日志被填满,然后进一步的写可能会被阻塞(这在理论上也可能发生在撤销日志中,但它需要更长的时间)。
  • 启动新事务的客户端将被迫在每次读取时对重做日志与旧数据页进行动态协调,至少在重做日志最终合并之前是这样。这对他们来说是一项非常繁忙的工作,而且有点遗憾,因为在OLTP数据库中启动新事务会更常见。

考虑到所有这些,似乎使用undo日志有助于优化最常见的情况:新事务读取最近提交的数据的新快照,作为直接从缓冲池中读取的页面。

最新更新