MySQL 二次写(Double Write Buffer)

95 阅读2分钟

什么是二次写

MySQL在将Buffer Pool中的数据持久化到磁盘中时,并不是直接将Buffer Pool中的内容持久化到磁盘里面或者说这个步骤并不仅仅如此。在写入到磁盘之前,还会将数据写入到一个叫做Double Write Buffer的内存缓冲区中。最后通过这个Double Write Buffer来将数据同步写入到磁盘的Double Write Buffer区域和数据页。具体过程类似下图: image.png(图片来自:博客园 赐我白日梦大佬)

存入整理流程如下

  • 如果需要修改的页面不在内存中,就进行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 完整写入了,也会导致崩溃恢复失败。