• 一看就懂的:MySQL的Double Write


    一、目录

    • 由断电引发的问题

    • 不一会 - 来电了

    • Double write工作流程

    • 恢复的过程

    • 配置参数

    • Double write并不一定是必须的

    • 疑问

    二、由断电引发的问题

    今天为大家介绍一个新的名词:double write。

    相信你还记得,我之前有写笔记跟大家分享过,在MySQL组织数据的基本单位是存在于磁盘上的数据页。数据页被读取到内存(Buffer Pool)中后被称为缓存页。默认情况下每个数据页的大小是16kb,数据页中存储的就是一行行真实的记录,也叫做数据行。

    1. mysql> SHOW GLOBAL VARIABLES LIKE 'innodb_page_size';
    2. +------------------+-------+
    3. | Variable_name    | Value |
    4. +------------------+-------+
    5. | innodb_page_size | 16384 |
    6. +------------------+-------+

    当有写操作对Buffer Pool中的数据页做了更新,我们把这种被改变过的数据页叫做:脏页。它是需要被刷新会磁盘的。这时问题就来了,对于计算机硬件或者是操作系统来说,每次原子IO操作的吞吐量量是小于16KB的,一般每个扇区的大小是512字节。

    1. # 文件系统块大小:一般为4k
    2. ~]# getconf PAGESIZE
    3. 4096
    4. ~]# fdisk -l
    5. 磁盘 /dev/sda:53.7 GB, 53687091200 字节,104857600 个扇区
    6. Units = 扇区 of 1 * 512 = 512 bytes
    7. 扇区大小(逻辑/物理):512 字节 / 512 字节
    8. I/O 大小(最小/最佳):512 字节 / 512 字节
    9. 磁盘标签类型:dos
    10. 磁盘标识符:0x000a88ef
    11.  设备 Boot      Start         End      Blocks   Id  System
    12. /dev/sda1   *        2048     2099199     1048576   83  Linux
    13. /dev/sda2         2099200   104857599    51379200   8e  Linux LVM
    14. 磁盘 /dev/mapper/centos-root:50.5 GB, 50457477120 字节,98549760 个扇区
    15. Units = 扇区 of 1 * 512 = 512 bytes
    16. 扇区大小(逻辑/物理):512 字节 / 512 字节
    17. I/O 大小(最小/最佳):512 字节 / 512 字节
    18. 磁盘 /dev/mapper/centos-swap:2147 MB, 2147483648 字节,4194304 个扇区
    19. Units = 扇区 of 1 * 512 = 512 bytes
    20. 扇区大小(逻辑/物理):512 字节 / 512 字节
    21. I/O 大小(最小/最佳):512 字节 / 512 字节

    那这么看来,当你想把一个16K大小的数据页写入到磁盘中时,结果刚写了4k,突然断电机器宕机了。那此时只有一部分是写入成功的。这就是大家常说的:partial page write

    三、不一会 - 来电了

    还是接着上面的描述说,不一会电源正常了,开机重启MYSQL,这时MySQL会进入到崩溃恢复的阶段。

    正常的崩溃恢复流程是:

    1. 将数据页从磁盘中读入到内存中

    2. 检查数据页中的LSN标记和redo log中的LSN谁更新,如果相同表示此时的数据页中的数据就是最新的,如果redo log的LSN比数据页中的LSN大,说明数据页中的数据是过时的数据,按redo重做出一份最新数据

    但是现在问题是:因为MySQL的Crash是由断电引发的,操作系统都没来得及将数据页完整的写入到磁盘中,导致崩溃恢复的第一步就失败了,因为MySQL会检查出:这个数据页是个不完整的数据页。

    四、Double write工作流程

    结合double write来看一下一条update sql的执行流程

    Step1: 满足update条件的数据页如果不再Buffer Pool中,就进行一次IO操作,将其加载进磁盘。

    Step2:  将该数据页修改成脏页。

    Step3: 当需要将缓冲池的脏页刷新到 data file 时,并不直接写到数据文件中,而是先拷贝至内存中的 double write buffer。

    Step4: 接着从 double write buffer 分两次写入磁盘共享表空间中,每次写入 1MB,并马上调用 fsync 函数,同步到磁盘,避免缓冲带来的问题。

    Step5: 完成Step2后,再将两次写缓冲区写入其对应的单独的数据文件。

    五、恢复的过程

    1. 将数据页从磁盘中读入到内存中

    2. 检查到数据页损坏了,尝试通过double write恢复数据。

    3. 如果 double write 的数据是完整的,用 double buffer 的数据页替换坏掉的数据页。

    那,如果 double write 中的数据页被写坏了怎么办?

    其实没关系,因为是先往共享表空间中写double write数据页,再往各个表对应的表空间文件中写实际的数据页,如果double write中的数据页坏点了,那恰恰说明,各个表对应的表空间文件中的数据页没坏!恢复的流程不会被打断!

    六、配置参数

    1. # 查看是否启用了double write,以及相关参数
    2. mysql> SHOW VARIABLES LIKE 'innodb_doublewrite%';
    3. +-------------------------------+-------+
    4. | Variable_name                 | Value |
    5. +-------------------------------+-------+
    6. | innodb_doublewrite            | ON    |
    7. | innodb_doublewrite_batch_size | 120   |
    8. +-------------------------------+-------+
    9. 2 rows in set (0.02 sec)
    10. # 查询double write的使用情况
    11. mysql> SHOW STATUS LIKE 'innodb_dblwr_%';
    12. +----------------------------+-------+
    13. | Variable_name              | Value |
    14. +----------------------------+-------+
    15. | Innodb_dblwr_pages_written | 14615 |   #从BP写入到dblwr的page数
    16. | Innodb_dblwr_writes        | 636   |   #写文件的次数
    17. +----------------------------+-------+
    18. 2 rows in set (0.02 sec)

    七、疑问

    看到这里你肯定已经知道了double write解决了数据页被写坏的情况,也就是说,redo log不能对一个本身就坏掉的数据页进行重做。

    但是,不知道你有没有这样的疑问,那redo log也是以文件的形式存在于磁盘上的,那假如在write redo log时,断电了呢?那redo log不也被损坏了?那还崩溃恢复个锤子?

    答:是这样的:事务产生的redo log先被组织成redo log block。并且redo log block其实就在redo log buffer 中。而redo log block的大小==操作系统一次原子IO的吞吐量512字节就像下图这样:

    八、Double并不一定是必须的

    并不是所有的场景都需要使用 Double Write 这样的机制来保证数据的安全准确性。比如 Solaris 平台上非常著名的 ZFS 文件系统,它就可以自己保证文件写入的完整性。

  • 相关阅读:
    web前端期末大作业:HTML+CSS+JavaScript绿色的盆栽花店网站响应式模板 大学生鲜花网页设计
    全网没有之一的JMeter 接口测试流程详解
    leetcode 26. 删除有序数组中的重复项(实现unique函数)
    专业韩语论文翻译,论文中译韩哪里比较专业?
    添加docker容器数据卷
    Windows 11 企业版新功能介绍
    横向柱状图数据配置
    乐盟互动申请纳斯达克IPO上市,募资2000万美元
    JAVA加密算法
    linux ansible(三)
  • 原文地址:https://blog.csdn.net/weixin_72753070/article/details/126171520