double write就是共享表空间的一部分,128个页(两个区),也就是2M,数据页在flush之前,会先把页面写入该区域,这样数据就相当于写了两次,成为两次写 为什么会有double write,直接从缓存写入磁盘岂不是更加快嘛,其实这是为了解决计算机或者操作系统在极端情况下不能保证操作的原子性,mysql默认数据页大小为16K,普通磁盘一个扇区是512字节,SSD一次写入大小为4K,所以对于16K的数据页来说需要多次I/O才能完成写入,如果中间出现意外,直接会导致数据页损坏。发生partial write的数据页不能通过redo进行恢复的,因为mysql在恢复过程中是检查page的checksum,checksum就是page最后的事务号,发生partial page write问题,page已经损坏了,找不到该page中的事务号,就没办法进行恢复。
为了解决 partial page write 问题,刷盘的流程变成如下步骤 内存中的脏页 >> double write buffer >> (分两次,一次1M)double write >> 调用fsync函数同步到对应的ibd文件中,就是磁盘中。 在上述过程中,double write是顺序写的,落盘是随机写的。 如果刷盘过程中,发生断电,那么恢复之后会通过double write buffer中的数据进行恢复。
–如果是写doublewrite buffer本身失败,那么这些数据不会被写到磁盘,InnoDB此时会从磁盘载入原始的数据,然后通过InnoDB的事务日志来计算出正确的数据,重新 写入到doublewrite buffer
–如果 doublewrite buffer写成功的话,但是写磁盘失败,InnoDB就不用通过事务日志来计算了,而是直接用buffer的数据再写一遍.
–在恢复的时候,InnoDB直接比较页面的checksum,如果不对的话,就从硬盘载入原始数据,再由事务日志 开始推演出正确的数据.所以InnoDB的恢复通常需要较长的时间