两次写
如果说Insert Buffer
带给InnoDB
存储引擎是性能上的提升,
那么两次写(double write
)带给InnoDB
存储引擎的是数据页的可靠性。
部分写
当发生数据库宕机时,可能InnoDB
存储引擎正在写入某个页到表中。
而这个页只写了一部分就发生了宕机,这种情况称为部分写失效(partial page write
)
如果发生写失效,不能通过重做日志恢复?
答:重做日志记录的是对页的物理操作,如果这个页本身已经损坏,
再对其进行重做是没有意义的。
在应用重做日志之前,需要一个页的副本,当出现部分写失效时,先通过页的副本
来还原该页,再进行重做,这就是
doublewrite
。
doublewrite 的组成
doublewrite
由两部分组成
内存中的
doublewrite buffer
,大小为2MB物理磁盘上共享空间中连续的128个页,即2个区(
extent
),同样为2MB这部分
doublewrite
是连续的,因此这个过程是顺序写的,开销并不是很大。
脏页刷新的步骤
在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是会通过memcpy
函数将脏页
先复制到内存中的doublewrite buffer
,之后通过doublewrite buffer
再分两次,
每次1MB顺序地写入共享表空间的物理磁盘上,然后马上调用fsync
函数,同步磁盘,
避免缓冲写带来的问题。
在完成doublewrite
页的写入后,再将doublewrite buffer
中的页写入各个表空间文件中,
此时就是刷新数据到数据库文件上,写入是离散的。
开启与关闭
可通过skip_innodb_doublewrite
参数禁止doublewrite
功能,这是可能会发生写失效问题。
某些文件系统本身提供了部分写失效的防范机制。如
ZFS
文件系统。这种情况下就不用开启
doublewrite
了。