欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(五)innodb关键特性之两次写(double Write)

程序员文章站 2022-05-04 12:49:55
...

InnoDB存储引擎的关键特性包括:

  • 插入缓冲(Insert Buffer)
  • 两次写(double Write)
  • 自适应哈希索引(Adaptive Hash Index)
  • 异步IO(Async IO)
  • 刷新邻接页(Flush Neighbor Page)
1. 应用场景

如果说Insert Buffer带给InnoDB存储引擎的是性能上的提升,那么double Write带给InnoDB存储引擎的是数据页的可靠性。当发生数据库宕机时,可能InnoDB存储引擎正在写入某个页到表中,而这个页只写了一部分,比如16K的页,只写了前4KB,之后发生了宕机,这种情况被称为部分写失效( partial page write ),从而导致数据丢失。

大家也许会问,难道我不可以根据redo log进行数据恢复吗?答案是看情况,分为两种情况:1、数据库宕机,物理文件完好无损,是可以通过redo log进行崩溃恢复。2、数据库宕机,正在刷新到磁盘的页发生partial page write,而正好在磁盘上的这个数据页由于宕机发生损坏,这时就无法通过redo log进行数据恢复了,为什么?我们必须要清楚的认识到,redo log里记录的是对页的物理操作!比如一条redo记录"page number xx,偏移量 800 写记录 “this is abc”",那当页损坏时,这条redo记录还有意义吗?于是在这种特殊情况下,doublewrite就派上用场啦!

2. double Write工作流程

doublewrite由两部分组成,一部分为内存中的doublewrite buffer,其大小为2MB,另一部分是磁盘上共享表空间(ibdata x)中连续的128个页,即2个区(extent),大小也是2M。doublewrite工作流程如下:

  1. 当一系列机制(main函数触发、checkpoint等)触发数据缓冲池中的脏页进行刷新时,并不直接写磁盘,而是会通过memcpy函数将脏页先复制到内存中的doublewrite buffer,之后通过doublewrite buffer再分两次、每次1MB顺序写入共享表空间的物理磁盘上。
  2. 马上调用fsync函数,同步脏页进磁盘。由于在这个过程中,doublewrite页的存储时连续的,因此写入磁盘为顺序写,性能很高;完成doublewrite后,再将脏页写入实际的各个表空间文件,这时写入就是离散的了。
    (五)innodb关键特性之两次写(double Write)

查看doublewrite工作情况,可以执行命令:

mysql> show global status like 'innodb_dblwr%'\G
*************************** 1. row ***************************
Variable_name: Innodb_dblwr_pages_written
        Value: 61932183
*************************** 2. row ***************************
Variable_name: Innodb_dblwr_writes
        Value: 15237891
2 rows in set (0.00 sec)

以上数据显示,doublewrite一共写了 61932183个页,一共写了15237891次,从这组数据我们可以分析,之前讲过在开启doublewrite后,每次脏页刷新必须要先写doublewrite,而doublewrite存在于磁盘上的是两个连续的区,每个区由连续的页组成,一般情况下一个区最多有64个页,所以一次IO写入应该可以最多写64个页。而根据以上我这个系统Innodb_dblwr_pages_written与Innodb_dblwr_writes的比例来看,大概在4左右,远远还没到64,所以从这个角度也可以看出,系统写入压力并不高。

参数skip_innodb_doublewrite可以禁止使用doublewrite功能。

3. 崩溃恢复

如果操作系统在将页写入磁盘的过程中发生崩溃,在恢复过程中,innodb存储引擎可以从共享表空间的doublewrite中找到该页的一个最近的副本,将其复制到表空间文件,再应用redo log,就完成了恢复过程。因为有副本所以也不担心表空间中数据页是否损坏。

相关标签: InnoDB引擎 innodb