我们知道,数据页被加载到内存中,经过增删改一系列的操作后,并不会立即落盘,而是由后台线程选择某个合适的时机写入磁盘。在数据页尚未落盘时,如果这时MySQL突然崩溃或者断电,内存中的数据将全部丢失。这时,redo log就可以发挥其作用了,只要重放redo log就可以恢复事务。
但是,MySQL的buffer一页的大小是16K,底层文件系统一页的大小是4K,换句话说,MySQL将一页buffer数据刷入磁盘,需要写到4个文件系统里的页。
假如MySQL内存中的一页数据准备刷入磁盘,才刷了2个(p1和p2)到文件系统里的页,这个时候停电或者机器宕机,当机器恢复后,buffer的页数据完整性已经遭到破坏,页发生了损坏,这时即使重放redo log也无法解决这样的问题了。因为这时页数据的结构很有可能已经改变(比如中间插入或删除了几条数据),而redo log是逻辑日志,记录的是哪个数据页的哪行记录做了什么更改,这时重放redo log没有任何意义,因为前后对应的记录大概率不是同一条了。
那么这时候,double write buffer的作用就体现出来了。MySQL在刷盘时,先将内存中的页数据写入内存中的double write buffer,然后将buffer中的数据先写入磁盘中的double write buffer文件,然后再写到磁盘中的数据页中,这就是(DoubleWrite)的由来。double write buffer中记录的是物理日志,即数据页的每条行数据。
故障分析:
1、如果系统在写入double Write Buffer前崩溃,那么重放redo log;
2、如果系统在写入磁盘的double write buffer时崩溃,说明还未写入磁盘中真正的数据页,重放redo log;
3、如果系统在写入到磁盘真正的数据页时崩溃,那么用double write buffer中的副本更新该数据页。