美文网首页MySQL
[MySQL]浅谈InnoDB存储引擎(五)两次写

[MySQL]浅谈InnoDB存储引擎(五)两次写

作者: AbstractCulture | 来源:发表于2020-10-20 13:46 被阅读0次

    回顾

    上个章节我们深入浅出了MySQL的Insert Buffer和新版本的InnoDB中支持的Change Buffer,从实现原理层面也做了一些探索。由此,我们可以给出结论,对于非聚簇非唯一的索引,通过Change Buffer可以让MySQL的DML操作更快,但是同时,也要注意Change Buffer膨胀导致缓冲池空间紧张的问题。OK,如果说Change Buffer给MySQL的DML操作带来了性能上的提升,那么今天我们来说一说InnoDB的另一个关键特性——doublewrite(两次写)。

    为什么需要两次写?

    • 数据库宕机导致数据丢失

    如果运行中的MySQL数据库突然发生宕机,此时InnoDB存储引擎正在将缓冲池中的页持久化到磁盘中,但是这个时刻数据库宕机了,那么会导致部分数据刷到了磁盘中,部分数据还在内存中,这种情况在MySQL中称为partial page write
    (部分写失效)。

    • redo log无法对页损坏做恢复

    redo log记录的是对页的物理操作,例如:偏移量800,写入'xxx'记录,但是页本身如果是损坏的,那么redo也是无济于事的。

    doublewrite是怎么做的?

    InnoDB在应用(apply)redo log前,写入了页的副本,当写入失效时,先通过副本还原该页,再进行redo。

    doublewrite结构

    • 内存中的doublewrite buffer

    大小为2MB

    • 物理磁盘上共享表空间中连续的128个页,即两个区(extent),大小为2MB。


      image.png

    doublewrite工作原理

    在对缓冲池的脏页进行刷新时,并不直接写入磁盘,而是会通过memcpy函数将脏页先复制到内存中的doublewrite buffer,之后通过doublewrite buffer再分两次,每次1MB顺序地写入共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘,避免缓冲写带来的问题。在这个过程中,因为doublewrite页是连续的,所以写入double write是顺序写的,开销并不是很大。等数据进入doublewrite的页后,再离散地将数据写入各个表空间文件中。

    查看doublewrite的运行情况

    > SHOW GLOBAL STATUS LIKE 'innodb_dblwr%'\G;
    
    • Innodb_dblwr_pages_written

    doublewrite写入缓存的页数

    • Innodb_dblwr_writes

    实际写入磁盘的次数

    系统在高峰时的Innodb_dblwr_pages_written:Innodb_dblwr_writes总体符合64:1,这对系统的IO压力并不是很高。

    通俗地理解doublewrite

    假设你要对一个表执行一段时间较长的SQL,你害怕在这段时间内MySQL断电了导致你的数据变脏了,虽然记录了SQL,但是你需要回到未执行这条SQL前的状态。那么你需要复制出一个一样的表,如果你的SQL失败,那么从copy的表中重新执行这条SQL。笔者认为,这便是doublewrite的思想。

    禁用doublewrite

    • skip_innodb_doublewrite

    通过这个参数,你可以禁用doublewrite。但是不建议这么做,任何时候,用户都应该开启doublewrite来保证你的MySQL具备容灾性。

    相关文章

      网友评论

        本文标题:[MySQL]浅谈InnoDB存储引擎(五)两次写

        本文链接:https://www.haomeiwen.com/subject/jglkmktx.html