透过doublewrite计数来预估系统写入压力

引自《MYSQL技术内幕innodb存储引擎》

  mysql有一个doublewrite的机制来保护数据的可靠性。想象一个场景,当数据库意外宕机时,某一个数据页正在写入。这个页可能只写了一部分,比如写了16K的前4K,这种情况我们称之为部分写失效(partial page write)。

  有人会说如果发生了写失效,可以通过重做日志来恢复。这个是一个办法。但是重做日志记录的是对数据页的物理操作,如偏移量100,写‘abc'记录。但是,如果这个页本身已经损坏,再对其进行重做是没有意义的。这就是说在apply redo log时,我们需要一个页的副本,当写入失效时,先通过页的副本来还原该页,在进行重做,这就是double write。Innodb doublewrite的体系架构如图:

wKioL1V48FuhSGZVAAFeqhtzyZg316.jpg  doublewrite由两部分组成:一部分是内存中的doublewrite buffer,大小为2MB;另一个部分是物理磁盘上共享表空间中连续的128个页,即两个区(extent),大小同样为2MB。当缓冲池的脏页刷新时,并不直接磁盘,而是会通过memcpy函数将脏页先考到内存中的doublewrite buffer中,然后通过doublewrite buffer分两次,每次写1MB到共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘,避免缓冲写带来的问题。在这个过程中,因为doublewrite页是连续的,因此这个过程是顺序写的,开销并不是很大。在完成doublewrite的写入后,再将doublewrite buffer中的页写入各个表空间文件中,此时的写入则是离散的。

  下面我们来看看doublewrite的运行状态:

  

 

mysql> show global status like 'innodb_dblwr%';

+----------------------------+--------+

| Variable_name              | Value  |

+----------------------------+--------+

| Innodb_dblwr_pages_written | 876623 |

| Innodb_dblwr_writes        | 62798  |

+----------------------------+--------+

2 rows in set (0.00 sec)

 

Innodb_dblwr_pages_written doublewrite写的总的页数,即一共写入了876623页,但实际写入的次数innodb_dblwr_writes62798。如果两个计数的比例远远小于64:1,则说明系统写入压力并不高。


如果操作系统在将页写入磁盘的过程中崩溃了,在恢复过程中,innodb存储引擎可以从共享表空间的doublewrite中找到改页的一个副本,将其拷贝到表空间文件,在应用重做日志。


注: 参数skip_innodb_doublewrite可以禁止使用两次写入功能。

你可能感兴趣的:(mysql)