InnoDB的double write的作用主要是为了防止部分写失效,即InnoDB默认的页是16k,而磁盘管理的页(即一次写磁盘的大小)一般不是16k,因此InnoDB一次写一个16k页时,操作系统和磁盘要多次写入,这样如果出现异常(断点或OS异常),会导致16k页只能部分写入。因为我们知道在flush buffer cache的时候,其实redo log已经写好了. 为什么还需要担心partial write呢? 这是因为mysql在恢复的时候是通过检查page的checksum来决定这个page是否需要恢复的, checksum就是当前这个page最后一个事务的事务号; 如果系统找不到checksum, mysql也就无法对这行数据执行写入操作;
另外redo log有的时候也是没法恢复数据的,
REDO LOG的记录有两种类型,一种叫做physical redo log,它记录更新后的整个Page的数据,另外一种叫做logical redo log,它仅记录在原始数据的基础上如何完成更新操作。
当REDO LOG是logical redo log时,如果原始数据已经被破坏(发生了partial page write ),那么就无法恢复数据了。
InnoDB的redo log是logical redo log,一条redo log 记录的是原来的更新的记录是关联的,如INSERT记录的redo log和它插入的前一条记录有关联的,如果前一条记录不完整,则这条redo log是没法恢复数据的。因此redo log作为恢复数据需要保证原来页的完整性,但部分写会破坏页的完整性。
Double write 由2部分组成,一部分是内存中的double write buffer ,大小为2MB;另一部分是INNODB在 tablespace上的128个页(2个区),大小也是2MB;
doublewrite技术的基本操作是:当InnoDB需要向磁盘刷新数据时,先把数据写入到doublewrite buffer(一般位于main tablespace),
将doublewrite buffer的内容同步写到磁盘,然后刷新到磁盘(即将可能被操作系统保存在内存中的文件内容,真正写入磁盘),然后再将写入到double write buffer中对应的页写入到磁盘,再刷新到磁盘。如果发生了极端情况(断电),InnoDB再次启动后,发现了一个Page数据已经损坏,那么此时就可以从doublewrite buffer中进行数据恢复了。
函数: buf_flush_post_to_doublewrite_buf(写到double write buffer)->buf_flush_buffered_writes(两次写盘和刷新磁盘, 第一次是double write buffer,然后是真正的页)