从MySQL innoDB的特性Doublewrite buffer谈起

前言

来分享下我对MySQL innoDB引擎的特性之一:Doublewrite Buffer的理解。
我争取把想要表达的东西讲清楚~

捋之前先明确几个知识点

  • MySQL InnoDB引擎默认IO的页大小为16k(可调整大小,但不推荐);操作系统的磁盘IO大小一般为4K或者1k,并不固定
  • Doublewrite Buffer并不是内存开辟的一块区域,8.0.20之前是在系统表空间中,8.0.20之后是专门有了doublewrite files 。
什么是Doublewrite buffer

Doublewrite buffer并不是在内存中开辟的一块区域
Doublewrite buffer并不是在内存中开辟的一块区域
Doublewrite buffer并不是在内存中开辟的一块区域

虽然它叫buffer结尾,但它确实是在磁盘中开启的空间!!!

8.0.20之前是存在于系统表空间中,8.0.20之后是专门有了doublewrite files存储;
对于5.7的文档,也是说明了Doublewrite buffer存在于系统表空间
体现形式至少是两个文件,如下图格式

#ib_16384_0.dblwr
#ib_16384_1.dblwr

MySQL 8.0文档很清晰的描述了Doublewrite buffer
是在磁盘上的一块连续的空间

在学习Doublewrite buffer的过程中我翻阅了很多博客的文章,

发现很多博客将Doublewrite buffer描述地很不清晰,无法验证来源

1.比如Doublewrite buffer是在内存中的一块空间
2.还有类似双写是先写内存,再写系统表空间
3.还有类似下图的架构,来自于鼎鼎大名的《MySQL技术内幕》但是官网版本也不可考证,如果有hxd知晓的,请指正
在这里插入图片描述

等等这些理论都不可考究,至少在官网的描述中,我并没有看到这些逻辑,如果大伙儿有明白的,滴滴我。


如下图,官方架构描述
在这里插入图片描述

在这里插入图片描述

为什么不直接写
可能会写坏原磁盘页数据

为什么要叫它Doublewrite呢,双写分别是哪两次写,体现在了什么地方呢

第一次 将脏页写Doublewrite buffer
第二次 在落盘Doublewrite buffer之后,再将脏页写入它们所在磁盘的位置
如下图所示在官方文档中,15.11.1 InnoDB Disk I/O 明确说明了 两次写的逻辑
在这里插入图片描述

为什么需要Doublewrite buffer

MySQL InnoDB引擎默认IO的页大小为16k;操作系统的磁盘IO大小一般为4K或者1k,并不固定;
那么当InnoDB将脏页flush到磁盘的时候,需要多次磁盘IO将数据写入。


将脏页直接刷入磁盘的过程中,在其中某次IO之后,假使意外发生,断电或者服务器异常,刷盘终止;对于InnoDB来说,后续重启读到的页数据是个不完整甚至是错误的数据页;上述问题就是所谓partial write


重启InnoDB数据恢复是通过Redo Log来进行,应用 Redo Log有一个前提:数据页必须是完好无损的。要保证数据页的完整性,应用 Redo 日志之前需要修复损坏的数据页


综上所述8.0.20之后的doublewrite files就是在恢复过程中修复不完整的数据页

Doublewrite buffer的具体使用

分情况讨论下,Doublewrite buffer两次写在crash之后的作用,如有不当之处,请指正~

本文具体暂不讨论redo log 和bin log的恢复过程
以下的前提redo log 是完整的文件

1.假如还没有进行第一次写的时候crash了,也就是Doublewrite buffer和磁盘数据文件都没有写成功
那么重启恢复的过程中,原有磁盘数据文件一定是完整的,但文件中并没有buffer pool中的脏页
读取redo log进行回放数据

校验原有磁盘数据文件页是完整的 通过
校验原有磁盘数据文件页的LSN 和 redo log文件的LSN
根据原有磁盘数据文件页的LSN,确定redo log恢复文件的起点
恢复文件

2.假如第一次写成功,在往原有磁盘文件中写脏页的时候crash了,Doublewrite buffer拥有部分完整的数据
那么重启恢复的过程中,使用Doublewrite buffer中的页数据进行覆盖写入脏页进入原有磁盘文件,假如Doublewrite buffer中的页数据不完整可以丢弃不用。
读取redo log进行回放数据

校验磁盘数据文件页是完整的 通过
校验磁盘数据文件页的LSN 和 redo log文件的LSN
根据磁盘数据文件页的LSN,确定redo log恢复文件的起点
恢复文件

谈谈PgSQL和Oracle在这方面的处理

以下是摘录自 https://blog.csdn.net/enmotech/article/details/105423975

PostgreSQL是通过full_page_write来解决这个问题,就是在数据页第一次发生变更的时候将整个页面记录到xlog日志中,这样出了问题就有了完整的数据页加xlog日志进行恢复,这样做的缺点是大大增加了xlog的日志量,也对性能有一定影响

Oracle 中不是没有partial write的问题,而是Oracle 本身具有很多数据块的完整校验机制,写失败就直接回滚掉了,甚至在Oracle 11gR2版本还有写数据文件发现IO异常直接crash 实例的特性(当然是为了更好的保护数据库的完整性)。总的来讲我个人认为Oracle的安全性还是非常高的。通过简单分析,也能说明为什么很多存储复制软件来做Oracle容灾,在关键时刻备库不一定能正常打开就的原因就是这样。
————————————————
版权声明:本文为CSDN博主「数据和云」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/enmotech/article/details/105423975

从操作系统再看Doublewrite Buffer

在有些操作系统和磁盘,Doublewirte Buffer可能并不需要开启。
原子写在这些系统上是支持的,每次IO的大小是大于MySQL的页大小;
也就不存在 partial write;
如果都使用了支持原子写的fusion-io 等存储设备,那么double write机制会被自动disable。
同时官方建议将innodb_fush_method设置为o_direct,这样可以充分发挥硬件性能。
除了硬件等支持,那么传统等文件系统比如ext4/xfs/zfs/VxFS 是否支持原子写呢?
实际上ext4/xfs对原子写支持目前都不是非常优化,zfs是天然支持的,很早的版本就支持了,另类的文件系统;
另外veritas的VxFS也是支持的,其官网有相关的解释

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值