innodb关键特性之double write 02

1.前言

  如果说insert buffer带给innodb存储引擎的是性能上的提升,那么doublewrite(两次写),带给innodb存储引擎的是数据页的可靠性

2.部分写失效

  当发生数据库宕机时,可能innodb存储引擎正在写入某个页到表中,而这个页只写了一部分,比如16kb的页,只写了4kb,之后就发生了宕机,这种现象被称为部分写失效(partial page write).在innodb存储引擎未使用doublewrite技术前,曾经出现过因为部分写失效而导致数据丢失的现象。

3.错误区

  可能有些DBA认为若果发生写失效了话,可以通过重做日志进行恢复,但是你在用它进行恢复的时候,必须要知道重做日志记录的是对页的物理操作,如偏移量800,写‘aaa’记录,如果这个页的本身发生了损坏,再对其进行重做是没有意义的。因此,在应用重做日志之前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是doublewrite. 图如下:

  innodb关键特性之double write 02

4.doublewrite

  doublewrite有两部分组成,一部分是内存中的doublewrite buffer,大小2MB,另一部分是物理磁盘上共享表空间中连续的128个页,即2个区,大小同样为2MB,在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是会通过memcpy函数将脏页先复制到内存的doublewriter buffer,之后通过doublewrite buffer在分两次,每次1MB顺序写入共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘,避免缓冲写带来的问题,在这个过程中,因为doublewrite页是连续的,因此这个过程是顺序写的,开销并不是很大,在完成doublewrite页的写入后,再将doublewrite buffer中的页写入各个表空间文件中,此时的写入则是离散的。可以通过以下命令观察doublewrite运行情况

root@localhost 10:51:  [(none)]> show global status like innodb_dblwr%;
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Innodb_dblwr_pages_written | 12    |         #表示已经写入到双写缓冲中的页数
| Innodb_dblwr_writes        | 1     |         #已经执行完成的doublewrite写操作的次数
+----------------------------+-------+

如果发现系统在高峰是的innodb_dblwr_pages_written:innodb_dblwr_writes远远小于64:1,那么可以说明系统写入压力并不高。这里需要注意的是:开启doublewrite后,每次脏页刷新必须要先写doublewrite,而doublewrite存在于磁盘上的是两个连续的区,每个区由连续的页组成,一般情况下一个区最多有64个页,所以一次IO写入应该可以最多写64个页。

5.doublewrite恢复过程

  数据恢复有三种情况:

  第一种:脏数据写磁盘成功

  刷盘成功,找检查点,进行前滚、回滚就行了。

  第二种:共享表空间ibdata写失败

  如果是写共享表空间失败,那么这些数据不会被写到数据文件,数据库会认为这次刷盘从没发生过,MySQL此时会从磁盘载入原始的数据,然后找检查点,redo log前滚、回滚就行了。

  第三种:脏数据刷数据文件失败

  写共享表空间成功,但是写数据文件失败,在恢复的时候,MySQL直接比较页面的checksum,如果不对的话,直接从共享表空间的double write中找到该页的一个最近的副本,将其复制到表空间文件,再应用redo log,就完成了恢复过程。因为有副本所以也不担心表空间中数据页是否损坏。  

6.查看doublewrite是否开启 

root@localhost 10:51:  [(none)]> show variables like %double%;
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| innodb_doublewrite | ON    |
+--------------------+-------+

  这里也可以在配置文件中进行配置,不配置的话默认是开启的,如果想要关闭doublewrite的话,可以用skip_innodb_doublewrite参数

7.场景

  首先doublewrite这个特性在Mysql中是默认开启的,如果我们对于需要提供数据高可靠性的主服务器(master server),任何时候用户都应该确保开启doublewrite功能

  不过如果用户有多个从服务器(slave server),需要提供较快的功能(如在slave server上做的是RAID0),可以关闭该特性,还有的文件系统本身就提供了部分写失效的防范机制,如ZFS文件系统,在这种情况下,用户就不要启动doublewrite了。

  

 

 

 

      

innodb关键特性之double write 02

上一篇:Java 后端接受前端的嵌套 json 数据,并写入数据库


下一篇:数据库SQL语句