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

3
如果存在WAL(重做)日志,它将允许我们在不需要先更新数据结构的情况下将记录持久化到磁盘并提交事务。
既然您始终可以从重做日志中重新应用和更新数据结构以应对崩溃或故障,为什么我们还需要撤消日志呢?
我对这个问题的理解是,我们仍然需要撤消日志,因为:
1.如果我们在记录提交并持久化到磁盘之前使用记录更新数据结构,则可能需要在事务回滚时撤消数据结构中的更改。但是,我不明白为什么我们不能等待事务提交后再更新数据结构?这听起来比维护撤消日志更简单。
2.快照隔离。MVCC需要能够访问旧版本的记录的数据结构。使用撤消日志,它可以回到过去。没有撤消记录,就无法提供回溯功能。
我的理解是,即使存在重做日志,我们仍然需要撤消日志吗?

https://dba.stackexchange.com/questions/251982/disable-redo-logs-on-mariadb/307723#307723 - undefined
1个回答

2
假设提交操作比回滚操作更频繁。即,如果客户端不打算提交更新,则不会执行更新。回滚是例外情况。
当您执行更改时,更改将写入数据页,并将页面的旧版本写入撤消日志。更改还将写入重做日志以进行崩溃恢复。在提交时,唯一需要发生的事情就是现在认为新版本已经提交。在多版本并发控制快照不再需要它时,可以计划将撤消日志中的副本作为垃圾丢弃。实际上,可能会有给定行的多个版本存在于撤销日志中,以满足不同的快照需求。
如果没有撤销日志,一切都依赖于重做日志,那么后果将是:
执行更改只会写入重做日志。这在查询执行过程中略微加速。
但提交将被迫进行更多的工作。基本上,相当于崩溃恢复期间所做的工作,将重做日志条目与现有页面对比,并在那里重建“当前”已提交的版本。
重做日志对账无法发生,直到所有其他并发可重复读事务完成,因为它们仍然需要查看数据页中的旧版本数据。这可能是一个问题,因为重做日志有一个固定的大小;未完成的事务可能导致重做日志填满,然后进一步的写操作可能会被阻塞(理论上也可以使用撤销日志,但需要更长时间)。
启动新事务的客户端都将被强制对旧数据页动态对账重做日志进行每次读取,至少直到重做日志最终合并。这对他们来说是很繁琐的工作,而且有点可惜,因为在 OLTP 数据库中,新事务开始是更常见的情况。
考虑到所有这些,似乎使用撤销日志有助于针对最常见的情况进行优化:新事务读取最近提交的数据的新快照,作为直接从缓冲池中读取的页面。

我明白了。感谢您的详细解释!日志是在哪个级别上维护的?每行1个日志链?这不是太多的日志文件吗?还是说撤销日志已经折叠到索引结构本身中,就像Mvcc树一样? - user855
撤销日志与表空间和其他数据结构的其他部分一样,存储在页面中。在旧版本中,撤销日志位于系统表空间ibdata1中,在较新版本中,它们将其分离为一个或多个其他文件,但我认为它仍然以页面结构化。这样它也被缓存在缓冲池中。 - Bill Karwin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接