MySQL采用buffer机制,避免每次读写进行磁盘IO,提升效率:
《》
《》
《》
MySQL的buffer一页的大小是16K,文件系统一页的大小是4K,也就是说,MySQL将buffer中一页数据刷入磁盘,要写4个文件系统里的页。
如上图所示,MySQL里page=1的页,物理上对应磁盘上的1+2+3+4四个格。
那么,问题来了,这个操作并非原子,如果执行到一半断电,会不会出现问题呢?
会,这就是所谓的“
页数据损坏
”。
如上图所示,MySQL内page=1的页准备刷入磁盘,才刷了3个文件系统里的页,掉电了,则会出现:重启后,page=1的页,物理上对应磁盘上的1+2+3+4四个格,数据完整性被破坏。
画外音:redo无法修复这类“页数据损坏”的异常,修复的前提是“页数据正确”并且redo日志正常。
很容易想到的方法是,能有一个“副本”,对原来的页进行还原,这个存储“副本”的地方,就是
Double Write Buffer
。
Double Write Buffer
,但它与传统的buffer又不同,它分为内存和磁盘的两层架构。
画外音:传统的buffer,大部分是内存存储;而DWB里的数据,是需要落地的。
第一步
:页数据先
memcopy
到DWB的内存里;
第二步
:DWB的内存里,会先刷到DWB的磁盘上;
步骤2和步骤3要写2次磁盘,这就是“
Double Write
”的由来。
假设步骤2掉电,磁盘里依然是1+2+3+4的完整数据。
画外音:只要有页数据完整,就能通过redo还原数据。
自己实验了几十次,仍没能复现“页数据损坏”,在网上找了一个“页数据损坏”时,MySQL重启过程利用DWB修复页数据的图。
能够通过DWB保证页数据的完整性,但毕竟DWB要写两次磁盘,会不会导致数据库性能急剧降低呢?
(1)第一步,页数据
memcopy
到DWB的内存,速度很快;
(2)第二步,DWB的内存
fsync
刷到DWB的磁盘,属于
顺序追加写
,速度也很快;
(3)第三步,刷磁盘,随机写,本来就需要进行,不属于额外操作;
另外,128页(每页16K)2M的DWB,会分两次刷入磁盘,每次最多64页,即1M的数据,执行也是非常之快的。
(1)write-ahead-log之所以性能高,就是因为顺序追加写;
更具体的,InnoDB里有两个变量可以查看
double write buffer
相关的情况:
Innodb_dblwr_pages_written
show global status like "%dblwr%"
(1)在异常崩溃时,如果不出现“页数据损坏”,能够通过redo恢复数据;
(2)在出现“页数据损坏”时,能够通过double write buffer恢复页数据;
(1)不是一个内存buffer,是一个内存/磁盘两层的结构,是InnoDB里
On-Disk
架构里很重要的一部分;
架构师之路
架构师之路,坚持撰写接地气的架构文章
635篇原创内容
Official Account
相关文章:
《》
《》
《》
《》