InnoDB: Concept: Doublewrite

 17th November 2020 at 12:28pm

Doublewrite(双写)是为了避免出现 partial write(只更新了部分数据)的一种机制。

Doublewrite 会便得当 InnoDB 将页写进 data file 前,先将其写到一块单独的 doublewrite buffer 存储中。写完后才会将页从这块 buffer 中取出,写到 data file 中。

假如没有 partial write,设想下当 MySQL 写一个 16K 的数据落盘时,只写成功了 4K 后,机器掉电了。MySQL 重启后,能检测到这 4K 所在的数据是不完整的,但是它并无法恢复。即使有 redo log 也无法恢复,因为 redo log 只纪录发生了什么变化,但是一旦原来的数据被破坏了,也没法通过 redo log 来生成新的数据。

有了 doublewrite 机制后,MySQL 重启时可以尝试 恢复。有两种情况:

  • doublewrite buffer 本身出现 partial write:写 buffer 没成功,这些页直接丢弃即可,他们不会被写入 data file
  • data file 出现 partial write:可以在 doublewrite buffer 中找到相应的数据恢复

性能 上,启用了 doublewrite 虽然需要将同样的数据写两次,但是由于 doublewrite buffer 的写入是顺序的,而且是批量写再调 fsync(),事实上只 额外增加 5% - 10% 的消耗

如果文件系统或者存储介质自身能保证不出现 partial write,也可以配置 InnoDB 关闭掉 doublewrite。

InnoDB's Buffers and Files

References