Innodb Double Write

Innodb使用的一种非常有趣的技术是称为“doublewrite”的技术。这意味着Innodb在执行表空间写入时会写入两次数据 - 对日志文件的写入只执行一次。

那么为什么需要双写呢?在部分页面写入的情况下,需要存档数据安全性。Innodb不会将完整页面记录到日志文件中,而是使用所谓的“生理”日志记录,这意味着日志记录包含操作的页码以及操作数据(即更新行)和日志序列信息。这种日志记录结构是geat,因为它需要将更少的数据写入日志,但是它需要页面内部一致。它是哪个页面版本并不重要 - 它可能是“当前”版本,在这种情况下,Innodb将跳过页面升级操作或“前”,在这种情况下Innodb将执行更新。如果页面不一致,则恢复无法继续。

 

现在让我们谈谈部分页面写入 - 它们是什么以及它们为什么会发生。部分页面写入是指提交给OS的页面写入请求仅部分完成。例如,在16K Innodb页面中,只有前4KB更新,其他部分保持原状态。最常见的是部分页面写入发生在电源故障时。它也可能在操作系统崩溃时发生 - 操作系统有可能将您的16K写入分成几次写入,并且只在执行之间发生故障。拆分的原因可能是文件碎片 - 大多数文件系统默认使用4K块大小,因此16K可以使用多个碎片。此外,如果使用软件RAID,页面可能会出现在条带边框上,需要多个IO请求。如果硬件RAID没有电池备份缓存,则在发生电源故障时也会发生相同情况。如果向磁盘本身发出单次写入,即使断电也应该在理论上完成,因为驱动器内应该有足够的功率来完成它。老实说,我不知道是否总是如此 - 很难检查,因为它不是部分页面写入的唯一原因。我只知道它们往往会发生,在实施Innodb doublewirite之前,我有几个数据损坏。

那么双写如何工作呢?您可以将其视为在Innodb表空间内分配的另一个短期日志文件 - 它包含100页的空间。当Innodb从Innodb缓冲池刷新页面时,它会通过多个页面进行刷新。因此,几个页面将被写入双写缓冲区(顺序),fsync()被调用以确保它们进入磁盘,然后页面写入其真实位置并且第二次调用fsync()。现在恢复时,Innodb会检查双重缓冲区内容和页面的原始位置。如果页面在双写缓冲区中不一致,则它被简单地丢弃,如果它在表空间中不一致则从双写缓冲区中恢复。

双写缓冲区对MySQL性能有多大影响?即使双写需要每页写入两次,其开销也远远小于两倍。写入双写缓冲区是顺序的,因此非常便宜。它还允许Innodb保存在fsync()上 - 而不是为每个页面调用fsync()写Innodb提交多页写入并调用fsync(),这允许操作系统优化执行写入顺序并并行使用多个设备。这种优化可以在没有双重写入的情况下使用,但它只是同时实现的。因此,一般来说,由于使用doublewrite,我预计性能损失不会超过5-10%。

你能禁用双写吗?如果您不关心您的数据(即RAID0上的从站),或者您的文件系统保证您不存在部分页面写入,则可以通过设置innodb_doublewrite = 0来禁用双写。但是在大多数情况下不值得。

posted @ 2019-07-30 09:47  lightyear  阅读(267)  评论(0编辑  收藏  举报