InnoDB Double write

2010-02-4  |  12:57分类:MySQL  |  标签:  |  

记得刚开始看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

喜欢本文,那就收藏到:

9条评论 关于 “InnoDB Double write”

  1. isql 发表于: 二月 9th, 2010 11:24

    写得很详细,对了,BP中的数据写入到LogFile中,这里的LogFile是redo还是redo和undo一起的,现在想了解这块的工作原理。就是redo和undo这两者应该是同步的吧?

  2. orczhou 发表于: 二月 9th, 2010 17:05

    这里的log file是redo(或者说是transaction log),和undo 不是一回事。undo是放在InnoDB的datafile里面的。

  3. sweetdream_xia 发表于: 十二月 20th, 2011 11:39

    写的很清晰

  4. MySQL5.1 InnoDB Plugin 启动信息详解 以及与MySQL5.0的InnoDB启动信息对比 | OurMySQL | 我们致力于一个MySQL知识的分享网站 发表于: 三月 25th, 2012 22:06

    [...] 或者是苏普的对Doublewrite整理 InnoDB Double write [...]

  5. 不叫花花白 发表于: 四月 13th, 2012 12:49

    那么在InnoDB恢复时就很尴尬:在InnoDB的Log file中虽然知道这个数据页被修改了,但是却无法知道这个页被修改到什么程度,和这个页面相关的redo也就无法应用了。
    -----------
    不需要知道修改到什么程度嘛,把涉及到的redolog重新do一下不就解决了; 虽然可能做一些无用功,但全部重新应用总是能得到正确结果的,partial-page又不会破坏未修改的数据,只可能破坏已经修改的数据,而已经修改的数据都在redolog中记录,哪里尴尬了?

  6. 匿名 发表于: 五月 6th, 2012 13:06

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

    这个说法有问题吧。

    应该是总共执行了2249336次double write操作,将145373349个脏页写到了double buffer. 平均每次double write操作写了 64.6个脏页,大小约1M

  7. salley 发表于: 九月 12th, 2012 11:22

    我也表示一下疑问,Innodb_dblwr_writes为2249336,是写的次数,那每一次double write写多少个页面呢?

  8. icediaby 发表于: 二月 9th, 2013 17:47

    check [URL=http://www.karen-millen-outlet-online2013.com/ - karen?millen?outlet[/URL - with low price tebaGMQe [URL=http://www.karen-millen-outlet-online2013.com/ - http://www.karen-millen-outlet-online2013.com/ [/URL -

  9. pingwater 发表于: 七月 31st, 2013 10:34

    我觉得 http://www.mysqlperformanceblog.com/2006/08/04/innodb-double-write/
    解释的最清楚,由于innoDB 使用 “physiological” logging,这种log虽然小,但缺点就是恢复时要求比较高的一致性(不是简单的physicall log),在partial page writes情况下,一致性被破坏,所以为了弥补这种不足,才引入Double Write,Double Write能够在不太增加开销的情况下(优化只fsync一次),保证了写入data的一致性。


发表您的评论