共计 1742 个字符,预计需要花费 5 分钟才能阅读完成。
导读 | MySQL 采用 buffer 机制,避免每次读写进行磁盘 IO,提升效率,那么,问题来了,这个操作并非原子,如果执行到一半断电,会不会出现问题呢? |
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 里的数据,是需要落地的。
如上图所示,当有页数据要刷盘时:
画外音:DWB 由 128 个页构成,容量只有 2M。
步骤 2 和步骤 3 要写 2 次磁盘,这就是“Double Write”的由来。
假设步骤 2 掉电,磁盘里依然是 1 +2+3+ 4 的完整数据。
画外音:只要有页数据完整,就能通过 redo 还原数据。
假如步骤 3 掉电,DWB 里存储着完整的数据。
所以,一定不会出现“页数据损坏”问题。
画外音:写了 2 次,总有一个地方的数据是 OK 的。
自己实验了几十次,仍没能复现“页数据损坏”,在网上找了一个“页数据损坏”时,MySQL 重启过程利用 DWB 修复页数据的图。
可以看到,启动过程中:
分析 DWB 执行的三个步骤:
另外,128 页 (每页 16K)2M 的 DWB,会分两次刷入磁盘,每次最多 64 页,即 1M 的数据,执行也是非常之快的。
综上,性能会有所影响,但影响并不大。
画外音:
更具体的,InnoDB 里有两个变量可以查看 double write buffer 相关的情况:
可以通过:
show global status like "%dblwr%"
来进行查询。
MySQL 有很强的数据安全性机制:
double write buffer:
知其然,知其所以然。
思路比结论重要,希望大家有收获。