了解MySQL之Doublewrite Buffer使用

 更新时间:2025年08月29日 09:12:31   作者:DG0913L  
文章介绍了MySQL InnoDB的DoublewriteBuffer机制,通过内存+磁盘的双重写入(先写内存,再顺序追加到磁盘,最后写数据文件)确保页数据完整性,避免因掉电导致数据损坏,同时说明其工作原理及关键参数配置,强调性能影响较小

前言

上一篇文章MySQL之Adaptive Hash Index详解我们学习了InnoDB Adaptive Hash Index自适应哈希索引的工作原理。

其本质是将频繁访问数据页的索引键值以“Key”放在缓存中,“Value”为该索引键值匹配完整记录所在页面(Page)的位置,通过缩短寻路路径(Search Path)从而提升MySQL查询性能的一种方式。

今天我们就学习了解一下Doublewrite Buffer是什么?工作原理是怎样的?(双写缓冲区,缩写:DWB

一、不同程序的page

这里我们需要知道的是Doublewrite BufferMySQL放在官档目录“磁盘结构”中了,但真实情况是Doublewrite Buffer是内存+磁盘的结构。

官档地址:https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html

1.1 Linux系统的Page OR MySQL的Page 大小对比

操作系统可以看成是一个程序,作为程序而言,都有最小处理单位的说法,我们常见的服务器一般都是Linux操作系统,对应文件系统的页(OS Page)就可以看成是Linux操作系统与文件系统交互的最小单位。

可以通过下面的命令来查看:

[root@mysql2 ~]# getconf PAGESIZE
4096

通过结果可以看出,Linux文件系统页(OS Page)的大小是4KB

同样地,MySQL作为一个程序也是有最小交互单位的,即InnoDB Buffer Pool能处理的最小单位,可以通过以下SQL命令查看:

mysql> show variables like '%innodb_page_size%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
1 row in set (0.01 sec)

如上,MySQL页(Page)大小默认为16KB

1.2 不同大小Page的程序在交互过程中会出现什么问题

一般情况下,除了操作系统的页(OS Page)为4KB之外,其余程序的页(Page)都会大于等于操作系统的页大小,比如,Oracle的Page大小为8KB。

MySQL的Page大小也可以通过上面innodb_page_size参数指定(5.6版本以前,不可调整;5.6版本时,可自定义为8KB、4KB,但不能调大;5.7版本以后,才可以改成32KB、64KB。我们使用默认值即可。

我们知道操作系统的页大小和MySQL的页大小了,而且MySQL程序是跑在Linux操作系统上的,所以可以得出一个结论:MySQL将Buffer Pool中一页数据刷入磁盘,要写4个文件系统里的页。

如上图所示:

MySQL里Page 1的页,物理上对应磁盘的Page 1、Page 2、Page 3、Page 4四个页,假设MySQL内Page 1的页准备刷入磁盘,才刷了3个文件系统里的页,掉电了,则会出现重启后,MySQL内Page 1的页,物理上对应磁盘上的Page 1、Page 2、Page 3三个页,数据完整性被破坏。(Redo Log无法修复这类“页数据损坏”的异常,修复的前提是“页数据正确”并且Redo日志正常)

二、Doublewrite Buffer概念

针对上面出现的情况,如何解决这类“页数据损坏”的问题呢?

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

Doublewrite Buffer,它与传统的“Buffer”又不同,它分为内存和磁盘的两层架构。(传统的“Buffer”,大部分是内存存储;而DWB里的数据,是需要落地的)

三、Doublewrite Buffer工作流程

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

  • 页数据先memcopy到DWB的内存里;
  • DWB的内存里的数据页,会先刷到DWB的磁盘上;
  • DWB的内存里的数据页,再刷到数据磁盘存储.ibd文件上;

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

假设步骤2掉电,磁盘里依然是Page 1、Page 2、Page 3、Page 4的完整数据。只要有页数据完整,就能通过Redo Log还原数据;假如步骤3掉电,DWB磁盘结构里存储着完整的数据。所以,一定不会出现“页数据损坏”问题。同时写了DWB磁盘和Data File,总有一个地方的数据是OK的

为什么叫Doublewrite?

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

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

  • 页数据memcopy到DWB的内存,速度很快;
  • DWB的内存fsync刷到DWB的磁盘,属于顺序追加写,速度也很快;
  • 刷磁盘,随机写,本来就需要进行,不属于额外操作;
  • 另外,128页(每页16K)2M的DWB,会分两次刷入磁盘,每次最多64页,即1M的数据(所以图中我们的DWB磁盘结构分为了两部分),执行也是非常之快的。综上,性能会有所影响,但影响并不大

四、Doublewrite Buffer的参数

我们使用如下命令查询

mysql> show variables like '%double%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| innodb_doublewrite            | ON    |
| innodb_doublewrite_batch_size | 0     |
| innodb_doublewrite_dir        |       |
| innodb_doublewrite_files      | 2     |
| innodb_doublewrite_pages      | 4     |
+-------------------------------+-------+
5 rows in set (0.01 sec)


mysql> show global status like '%dblwr%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Innodb_dblwr_pages_written | 489   |
| Innodb_dblwr_writes        | 176   |
+----------------------------+-------+
2 rows in set (0.00 sec)

4.1 innodb_doublewrite

Doublewrite Buffer是否启用开关,默认是开启状态,InnoDB将所有数据存储两次,首先到双写缓冲区,然后到实际数据文件

如果关闭,需要在my.cnf文件中指定

[mysqld]
innodb_doublewrite = off

4.2 Innodb_dblwr_pages_written & Innodb_dblwr_writes

  • Innodb_dblwr_pages_written 是doublewrite写的总的页数,即一共写入了489页
  • innodb_dblwr_writes是实际写入的次数为176

如果两个计数的比例远远小于64:1,则说明系统写入压力并不高。

4.3 innodb_doublewrite_batch_size

  • 控制要批量写入的双写页数。
  • 此变量用于高级性能调整。
  • 默认值应该适合大多数用户(默认值是0,最大值是256)

4.4 innodb_doublewrite_dir

  • 定义了目录InnoDB创建双写文件。
  • 如果未指定innodb_data_home_dir目录,则在目录中创建双写文件,如果未指定,则默认为数据目录。

4.5 innodb_doublewrite_files

  • 定义了双写文件的数量。默认情况下,为每个缓冲池实例创建两个双写文件。
  • 双写文件的最大数量是缓冲池实例数量的两倍。(缓冲池实例的数量由innodb_buffer_pool_instances变量控制)

Doublewrite文件名具有以下格式:

例如,以下双写文件是为页面大小为16KB和单个缓冲池的MySQL实例创建的:

#ib_丨page_size_file_丨number.dblwr

所以我们的DWB文件就被创建成下面的模样:

[root@mysql2 data]# ll \#ib_16384_*
-rw-r----- 1 mysql mysql  327680 5月   4 12:40 #ib_16384_0.dblwr
-rw-r----- 1 mysql mysql 8716288 4月  26 16:54 #ib_16384_1.dblwr

4.6 innodb_doublewrite_pages

控制每个线程双写页的最大数目。如果未指定值,innodb_doublewrite_pages则设置为该innodb_write_io_threads值。

此变量用于高级性能调整。默认值应该适合大多数用户。(最小值和默认值一样,都是innodb_write_io_threads的值,最大值是256)

今天主要讲解了MySQL InnoDB Doublewrite Buffer的工作原理,通过流程图的方式来说明Doublewrite Buffer的工作流程,偏理论的知识,内容比较少也很好理解,大家理解记忆即可,面试也会遇到这个知识点。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • MySQL server has gone away的问题解决

    MySQL server has gone away的问题解决

    本文主要介绍了MySQL server has gone away的问题解决,意思就是指client和MySQL server之间的链接断开了,下面就来介绍一下几种原因及其解决方法,感兴趣的可以了解一下
    2024-07-07
  • MySQL的LEFT JOIN表连接的进阶学习教程

    MySQL的LEFT JOIN表连接的进阶学习教程

    这篇文章主要介绍了MySQL的LEFT JOIN表连接的进阶学习教程,包括对左连接的查询效率分析以及相关建议,需要的朋友可以参考下
    2015-12-12
  • SQL基础的查询语句

    SQL基础的查询语句

    这篇文章主要给大家分享的是SQL基础的查询语句,SQL语句中,查询是使用最多的操作,SQL不仅能够查询表中的数据,还可以返回算术运算、表达式的结果等,接下来就一起了解一下基本的查询语句,需要的朋友可以参考一下
    2021-11-11
  • mysql巡检脚本(必看篇)

    mysql巡检脚本(必看篇)

    下面小编就为大家带来一篇mysql巡检脚本(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • MySQL修改root密码的多种方法(推荐)

    MySQL修改root密码的多种方法(推荐)

    本文给大家分享了三种方法来解决mysql修改root密码的方法,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2017-03-03
  • MYSQL中文乱码问题的解决方案

    MYSQL中文乱码问题的解决方案

    mysql是我们项目中非常常用的数据型数据库,但是因为我们需要在数据库保存中文字符,所以经常遇到数据库乱码情况这篇文章主要给大家介绍了关于MYSQL中文乱码问题的解决方案,需要的朋友可以参考下
    2022-06-06
  • Mysql中where与having的区别实例详解

    Mysql中where与having的区别实例详解

    当SQL语句中使用聚合函数,然后又需要对聚合函数的记录集进行筛选过滤时,这个时候就需要用到Having子句,下面这篇文章主要给大家介绍了关于Mysql中where与having区别的相关资料,需要的朋友可以参考下
    2023-01-01
  • 云服务器Ubuntu_Server_16.04.1安装MySQL并开启远程连接的方法

    云服务器Ubuntu_Server_16.04.1安装MySQL并开启远程连接的方法

    这篇文章主要介绍了云服务器Ubuntu_Server_16.04.1安装MySQL并开启远程连接的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-02-02
  • 安装mysq 5.7.20 解压版遇到的坑(推荐)

    安装mysq 5.7.20 解压版遇到的坑(推荐)

    最近有朋友说当mysql5.7.20解压版环境变量配置好后,根目录没有my.ini 也没有 my-default.ini文件,怎么处理这个问题呢,下面小编给大家带来了解决方案,大家可以参考下
    2017-11-11
  • mysql如何用sql语句建立学生课程数据库基本表

    mysql如何用sql语句建立学生课程数据库基本表

    这篇文章主要给大家介绍了关于mysql如何用sql语句建立学生课程数据库基本表的相关资料,学生表是一个常见的数据表,用于存储学生的个人信息和成绩等相关数据,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-12-12

最新评论