什么是二次写
MySQL在将Buffer Pool中的数据持久化到磁盘中时,并不是直接将Buffer Pool中的内容持久化到磁盘里面或者说这个步骤并不仅仅如此。在写入到磁盘之前,还会将数据写入到一个叫做Double Write Buffer的内存缓冲区中。最后通过这个Double Write Buffer来将数据同步写入到磁盘的Double Write Buffer区域和数据页。具体过程类似下图:
(图片来自:博客园 赐我白日梦大佬)
存入整理流程如下
- 如果需要修改的页面不在内存中,就进行io将数据放到内存中来
- 将数据页修改为脏页
- 将脏页数据写入到Double Write Buffer中
- 同时将DWB中的内容写入到共享表空间和数据文件中
数据恢复流程
- 首先会看redolog和数据库表中的LSN(log sequence number)和CheckSum是否相同。如果不同就看共享表空间中的内容是否相同。相同就把共享表中的数据来替代数据库表来做redo的数据页进行恢复
为什么会需要二次写
因为Linux的物理页大小为4kb,而MySQL的物理页大小为16kb,在刷盘时如果出现partial page write(部分页面写入)的话,就会导致数据文件中的MySQL页面不是一致的(即一个页面中有新老数据)。但是redo log恢复数据是需要完整的数据页的。因此, 需要二次写来辅助redo log进行崩溃恢复时,恢复的数据是有效的、完整的、正确的。
问题
虽然引入Double Write Buffer能够帮助redo log做崩溃恢复,但是感觉同时也引入了一些可能出现问题的点,例如:
- 如果我们在写入Double Write Buffer是掉电或者系统崩溃。但是redo log 完整写入了,也会导致崩溃恢复失败。