IT技术博客大学习 共学习 共进步

InnoDB Double write

DBA@Taobao 2010-03-01 14:01:29 浏览 4,261 次

记得刚开始看InnoDB文档的时候,Double Write一节(其实只有一小段)就让我很困惑。无奈当时内力太浅,纠缠了很久也没弄明白。时隔几个月,重新来整理一下。

涉及到的概念:Buffer Pool简称BP,Dirty PageLog fileFlushinnodb tablespace

1. 什么是Double Write

在InnoDB将BP中的Dirty Page刷(flush)到磁盘上时,首先会将Page刷到InnoDB tablespace的一个区域中,我们称该区域为Double write Buffer。在向Double write Buffer写入成功后,再择机将数据拷贝到正在的数据文件对应的位置。

咋一看,这个过程有些多余

2. 为什么需要Double Write

InnoDB中有记录(Row)被更新时,先将其在Buffer Pool(简称BP)中的page更新,并将这次更新记录到Log file中,这时候BP中的该page就是被标记为Dirty。在适当的时候(BP不够、系统闲置等),这些Dirty Page会被flush到磁盘上。

试想,在某个Dirty Page(一般是16K)flush的过程中,发生了系统断电(或者OS崩溃),16K的数据只有8K被写到磁盘上,这种现象被称为(partial page writes、torn pages、fractured writes)。一旦partial page writes发生,那么在InnoDB恢复时就很尴尬:在InnoDB的Log file中虽然知道这个数据页被修改了,但是却无法知道这个页被修改到什么程度,和这个页面相关的redo也就无法应用了。

举个例子:在InnoDB的log file中有如下Log:

Log sequence number 0 4285149977
Log sequence number 0 4287355447
Log sequence number 0 4289260680
Log sequence number 0 4291279900
Log sequence number 0 4293359020

其中第1、3个Log修改了该page,但是在断电时,BP中该page只被flush了一部分。那么InnoDB是无法决定上面的Log是否应该被应用的。这时,数据就出现了不一致。

所以,Log file的有效应用,前提是InnoDB的数据文件中的Page是一致的。

简而言之,Double write就是为了避免Partial page writes而设计的。

3. Double Write对性能的影响

系统需要将数据写两份,一般认为,Double Write是会降低系统性能的。peter猜测可能会有5-10%的性能损失,但是因为实现了数据的一致,是值得的。Mark Callaghan认为这应该是存储层面应该解决的问题,放在数据库层面无疑是牺牲了很多性能的。

事实上,Double Write对性能影响并没有你想象(写两遍性能应该降低了50%吧?)的那么大。在BP中一次性往往会有很多的Dirty Page同时被flush,Double Write则把这些写操作,由随机写转化为了顺序写。而在Double Write的第二个阶段,因为Double Write Buffer中积累了很多Dirty Page,所以向真正的数据文件中写数据的时候,可能有很多写操作可以合并,这样有可能会降低Fsync的调用次数。

基于上面的原因,Double Write并没有想象的那么糟。另外,Dimitri在测试后,发现打开和关闭Double Write对效率的影响并不大。

4. 相关参数与状态

是否打开了double write:

root@(none) 07:16:16>show variables like "%double%";
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| innodb_doublewrite | ON    |
+--------------------+-------+

Double write的使用情况:

root@(none) 07:15:50>SHOW STATUS LIKE "%innodb_dblwr%";
+----------------------------+-----------+
| Variable_name              | Value     |
+----------------------------+-----------+
| Innodb_dblwr_pages_written | 145373349 |
| Innodb_dblwr_writes        | 2249336   |
+----------------------------+-----------+

上面可以看到,从BP共Flush了145373349个Pages到double write buffer中;一共调用了2249336次write写到真正的数据文件。可见,相当于每次write合并了 145373349 / 2249336 = 64.6次Flush。(这就是为什么double write buffer为什么并不会对效率有很大影响的原因)

5. 我的看法

在某些文件系统(ZFS等)层面能够保证不出现Partial page writes时,可以关闭Double Write。因为它对性能影响并不大,一般情况都建议打开,毕竟带来的数据安全性保障可能是我们更关心的。

参考文献:

[0]. Manual about Double Write

[1]. Innodb Double Write

[2]. Do you need the InnoDB doublewrite buffer

[3]. MySQL Performance: InnoDB Doublewrite Buffer Impact

建议继续学习

  1. Innodb IO优化-配置优化 (阅读 7,603)
  2. Innodb分表太多或者表分区太多,会导致内存耗尽而宕机 (阅读 7,565)
  3. Innodb 表和索引结构 (阅读 6,041)
  4. InnoDB线程并发检查机制 (阅读 5,601)
  5. Innodb如何使用内存 (阅读 5,102)
  6. Innodb文件表空间结构 (阅读 5,063)
  7. 快速预热Innodb Buffer Pool的方法 (阅读 4,983)
  8. InnoDB的缓存替换策略及其效果 (阅读 4,782)
  9. 多版本并发控制:PostgreSQL vs InnoDB (阅读 4,561)
  10. InnoDB之Dirty Page、Redo log (阅读 4,481)