突然断电,是否会影响Mysql的执行结果

admin4个月前笔记73

MySQL采用buffer机制,避免每次读写进行磁盘IO,提升效率:

  • 《缓冲池(buffer pool)》

  • 《写缓冲(change buffer)》

  • 《日志缓冲(log buffer)》

  • MySQL的buffer一页的大小是16K,文件系统一页的大小是4K,也就是说,MySQL将buffer中一页数据刷入磁盘,要写4个文件系统里的页。

    image.png

    如上图所示,MySQL里page=1的页,物理上对应磁盘上的1+2+3+4四个格。

    那么,问题来了,这个操作并非原子,如果执行到一半断电,会不会出现问题呢?

    会,这就是所谓的“页数据损坏”。

    image.png

    如上图所示,MySQL内page=1的页准备刷入磁盘,才刷了3个文件系统里的页,掉电了,则会出现:重启后,page=1的页,物理上对应磁盘上的1+2+3+4四个格,数据完整性被破坏。

    画外音:redo无法修复这类“页数据损坏”的异常,修复的前提是“页数据正确”并且redo日志正常。

    如何解决这类“页数据损坏”的问题呢?

    很容易想到的方法是,能有一个“副本”,对原来的页进行还原,这个存储“副本”的地方,就是Double Write Buffer。

    Double Write Buffer,但它与传统的buffer又不同,它分为内存和磁盘的两层架构。

    画外音:传统的buffer,大部分是内存存储;而DWB里的数据,是需要落地的。

    image.png

    如上图所示,当有页数据要刷盘时:

  • 第一步:页数据先memcopy到DWB的内存里;

  • 第二步:DWB的内存里,会先刷到DWB的磁盘上;

  • 第三步:DWB的内存里,再刷到数据磁盘存储上;

  • 画外音:DWB由128个页构成,容量只有2M。

    步骤2和步骤3要写2次磁盘,这就是“Double Write”的由来。

    DWB为什么能解决“页数据损坏”问题呢?

    假设步骤2掉电,磁盘里依然是1+2+3+4的完整数据。

    画外音:只要有页数据完整,就能通过redo还原数据。

    假如步骤3掉电,DWB里存储着完整的数据。

    所以,一定不会出现“页数据损坏”问题。

    画外音:写了2次,总有一个地方的数据是OK的。

    自己实验了几十次,仍没能复现“页数据损坏”,在网上找了一个“页数据损坏”时,MySQL重启过程利用DWB修复页数据的图。

    image.png

    可以看到,启动过程中:

  • InnoDB检测到上一次为异常关闭;

  • 尝试恢复ibd数据,失败;

  • 从DWB中恢复写了一半的页;

  • 能够通过DWB保证页数据的完整性,但毕竟DWB要写两次磁盘,会不会导致数据库性能急剧降低呢?

    分析DWB执行的三个步骤:

  • 第一步,页数据memcopy到DWB的内存,速度很快;

  • 第二步,DWB的内存fsync刷到DWB的磁盘,属于顺序追加写,速度也很快;

  • 第三步,刷磁盘,随机写,本来就需要进行,不属于额外操作;

  • 另外,128页(每页16K)2M的DWB,会分两次刷入磁盘,每次最多64页,即1M的数据,执行也是非常之快的。

    综上,性能会有所影响,但影响并不大。

    画外音:

  • write­-ahead-log之所以性能高,就是因为顺序追加写;

  • 有第三方测评,评估约10%性能损失;

  • 更具体的,InnoDB里有两个变量可以查看double write buffer相关的情况:

  • Innodb_dblwr_pages_written:记录写入DWB中页的数量。

  • Innodb_dblwr_writes:记录DWB写操作的次数。

  • 可以通过:

    show global status like "%dblwr%"

    来进行查询。

    image.png

    结尾

    MySQL有很强的数据安全性机制:

  • 在异常崩溃时,如果不出现“页数据损坏”,能够通过redo恢复数据;

  • 在出现“页数据损坏”时,能够通过double write buffer恢复页数据;

  • double write buffer:

  • 不是一个内存buffer,是一个内存/磁盘两层的结构,是InnoDB里On-Disk架构里很重要的一部分;

  • 是一个通过写两次,保证页完整性的机制;

  • 知其然,知其所以然。


相关文章

在nginx配置将请求转发到某个真实后端服务ip

在nginx配置将请求转发到某个真实后端服务ip

一、打开nginx机器的nginx配置文件命令:locate nginx.conf会列出所有nginx.conf文件的地址,一般咱们要用的nginx配置文件是/usr/local/nginx...

MySQL管理端口登录异常排查及正确使用技巧

1背景描述MySQL 8.0.14 版本中引入了 admin_port参数,用于提供一个管理端口来处理 too many connections报错。最近一套 MySQL 8.0...

分享一条history命令小技巧

在使用linux终端执行bash的时候,发现怎么没有时间标识呢,这以后还怎么查是哪天执行了那条命令呢。这个history的作用就是将bash执行过的所有命令存储到.bash_history文件中,帮助...

教你如何让页面与 iframe 进行通信

引言这篇文章介绍如何实现页面与 iframe 进行通信,实际工作中可能很难遇到,但一旦遇到了,我们要能够立即想到怎样去实现。iframe 向父级页面发送消息在 iframe 页面,使用 window....

勒索病毒下数据安全的反思

勒索病毒下数据安全的反思

互联网时代的蓬勃发展,带来的便利和未来的期待的超越想象,同时也不可避免的增加了个人资料个人隐私泄密的风险。这次的勒索病毒事件,同时也曝露了数据安全的重要性,全球陷入恐慌中。而路透也援引数据称,勒索病毒...

linux shell “(())” 双括号运算符使用

linux shell “(())” 双括号运算符使用

使用方法:语法:((表达式1,表达式2…))特点:1、在双括号结构中,所有表达式可以像c语言一样,如:a++,b--等。 2、在双括号结构中,所有变量可以不加入:“$”符号前缀。 3、双括号可以进...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。