提问1: 为啥 Binlog 没有 crash-safe 功能?
redo log 和 binlog 有一个很大的区别就是,一个是循环写,一个是追加写。也就是说 redo log 只会记录未刷盘的日志,已经刷入磁盘的数据都会从 redo log 这个有限大小的日志文件里删除。binlog 是追加日志,保存的是全量日志。
当数据库 crash 后,想要恢复未刷盘但已经写入 redo log 和 binlog 的数据,binlog 是无法恢复的。虽然 binlog 拥有全量的日志,但没有一个标志让 innodb 判断哪些数据已经刷盘,哪些数据还没有
举个例子, binlog 记录了两条日志:
1. 给 ID = 2 这一行的 c 字段加1
2. 给 ID = 2 这一行的 c 字段加2
在记录1刷盘后,记录2未刷盘时,数据库 crash。重启后,只通过 binlog 数据库无法判断这两条记录哪条已经写入磁盘,哪条没有写入磁盘,不管是两条都恢复至内存,还是都不恢复,对 ID=2 这行数据来说,都不对
但 redo log 不一样,只要刷入磁盘的数据,都会从 redo log 中抹掉,数据库重启后,直接把 redo log 中的数据都恢复至内存就可以了。这就是为什么 redo log 具有 crash-safe 的能力,而 binlog 不具备
提问2: 保证 crash-safe 为啥要用两个日记,不能用一个日记吗(Redo log 或 Binglog)?
针对问题1我们知道只有 binlog 日志,没有 redo log 是不能做到故障恢复的。那么针对只有 redo log日志,没有 binlog 日志,这也是不行的,因为 redo log 是 innodb 持有的,且日志上的记录落盘后会被抹掉。因此需要 binlog 和 redo log 两者同时记录,才能保证当数据库发生宕机重启时,数据不会丢失。