在服务器不挂的情况下,redo 日志简直就是个大累赘,不仅没用,反而让性能变得更差。但是万一数据库挂了,就可以在重启时根据 redo 日志中的记录就可以将页面恢复到系统崩溃前的状态。
MySQL 可以根据 redo 日志中的各种 LSN 值,来确定恢复的起点和终点。然后将 redo 日志中的数据,以哈希表的形式,将一个页面下的放到哈希表的一个槽中**。之后就可以遍历哈希表,因为对同一个页面进行修改的 redo 日志都放在了一个**槽里,所以可以一次性将一个页面修复好(避免了很多读取页面的随机 IO)。并且通过各种机制,避免无谓的页面修复,比如已经刷新的页面,进而提升崩溃 恢复的速度。

崩溃后的恢复为什么不用binlog?

1、这两者使用方式不一样
binlog 会记录表所有更改操作,包括更新删除数据,更改表结构等等,主要用于人工恢复数据,而 redo log 对于我们是不可见的,它是 InnoDB 用于保证crash-safe 能力的,也就是在事务提交后 MySQL 崩溃的话,可以保证事务的持久性,即事务提交后其更改是永久性的。
一句话概括:binlog **是用作人工恢复数据,redo log MySQL**自己使用, 用于保证在数据库崩溃时的事务持久性。

2、redo** log InnoDB 引擎特有的binlog MySQL Server 层实现的**, 所有引擎都可以使用。

3、redo log **是物理日志,记录的是“在某个数据页上做了什么修改”,恢复**的速度更快;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这的 c 字段加 1 ” ;

4、redo log 是“循环写”的日志文件,redo log 只会记录未刷盘的日志,已经刷入磁盘的数据都会从 redo log 这个有限大小的日志文件里删除。binlog 是追加日志,保存的是全量的日志。

5、最重要的是,当数据库 crash 后,想要恢复未刷盘但已 经写入 redo log 和binlog 的数据到内存时,binlog 是无法恢复的。虽然 binlog 拥有全量的日志, 但没有一个标志让 innoDB 判断哪些数据已经入表(写入磁盘),哪些数据还没有。
比如,binlog 记录了两条日志: 给 ID=2 这一行的 c 字段加 1 给 ID=2 这一行的 c 字段加 1
在记录 1 入表后,记录 2 未入表时,数据库 crash。重启后,只通过 binlog 数据库无法判断这两条记录哪条已经写入磁盘,哪条没有写入磁盘,不管是两条都恢复至内存,还是都不恢复,对 ID=2 这行数据来说,都不对。
但 redo log 不一样,只要刷入磁盘的数据,都会从 **redo log **中抹掉,数据库重启后,直接把 redo log 中的数据都恢复至内存就可以了。