Skip to main content

Doublewrite Buffer

作用

Doublewrite Buffer 作用是,在把页写到数据文件之前,InnoDB先把它们写到一个叫doublewrite buffer(双写缓冲区)的共享表空间内,在写doublewrite buffer完成后,InnoDB才会把页写到数据文件的适当的位置。如果在写页的过程中发生意外崩溃,InnoDB在稍后的恢复过程中在doublewrite buffer中找到完好的page副本用于恢复,所以本质上是一个最近写回的页面的备份拷贝。

Doublewrite Buffer 也可能出错,他解决的问题是?

双写缓冲区的主要保护对象是“最终写入”过程中的部分失败,而不是保护自己。

对于双写缓冲区自身的部分写失败,MySQL 的崩溃恢复流程中有一段特殊处理:它会扫描整个双写缓冲区,只使用那些完整且校验和正确的页去修复表空间;损坏的页会被忽略,然后回退到 Redo Log 恢复。

而如果最终位置的页是完好的(哪怕双写缓冲区坏了),直接用 Redo Log 就可以恢复,不需要双写缓冲区。

所以你的结论是正确的:中转写入并不能 100% 避免出错,只是把风险从“大面积随机写入”转移到了一个更可控的连续小块区域,并且增加了校验机制来识别坏副本。本质上是一个概率和工程权衡——用极低的额外代价,把数据页损坏的概率从“不可忽略”降到“在实际系统中几乎观测不到”。

为什么叫 Doublewrite Buffer 而不是 Single Write buffer

这个问题问得很巧妙,触及了命名背后的准确含义。

之所以叫 Doublewrite Buffer(双写缓冲区),而不是 Single Write Buffer,核心原因在于:数据被完整地写了两次

  • 第一次写:将数据页写入 Doublewrite Buffer(一块连续的磁盘暂存区)。
  • 第二次写:再将同一个数据页从 Doublewrite Buffer 写入 表空间的最终位置

所以,“Doublewrite”指的是“写入动作发生了两次”,而不是“缓冲区有两份”或“缓冲区大小是双倍”。如果是“Single Write”,那就意味着只写一次(直接写表空间),那就根本无法解决部分页写失败的问题——因为一旦写一半崩溃,没有完整的备份可用来恢复。

你之前理解得非常准确:Doublewrite Buffer 是一个“中转站”。但注意,这个中转站本身并不是“写一次”就结束的,而是必须配合第二次写入才能真正起到保护作用。因此,整个机制的全称是“双写机制”,其缓冲区自然就叫 Doublewrite Buffer。

换个角度想:如果它叫 Single Write Buffer,会让人误解为“我只往这个缓冲区写一次数据,就完事了”,那表空间的最终位置永远是旧的或损坏的,显然不合理。

总结一句话
命名强调的是写入的次数(两次),而不是缓冲区的形态。正是这个“双重写入”的过程,才让你之前理解的“有余地”成为现实——第一次写保留了完整副本,第二次写是真正的投递,两次写互为备份与恢复的依据。