MYSQL之Doublewrite Buffer双写缓存区详解

 更新时间:2025年08月29日 10:06:30   作者:程序猿夏夏夏  
由于MySQL页(16KB)与Linux文件系统页(4KB)不匹配,可能导致部分页写入损坏,Redo日志无法修复,Doublewrite Buffer通过内存+磁盘双缓冲确保数据可靠性,与Redo日志协作实现故障恢复,相关参数用于配置

为什么需要Doublewrite Buffer

我们常见的服务器一般都是Linux操作系统,Linux文件系统页(OS Page)的大小默认是4KB。而MySQL的页(Page)大小默认是16KB。

可以使用如下命令查看MySQL的Page大小:

SHOW  VARIABLES  LIKE  'innodb_page_size';

一般情况下,其余程序因为需要跟操作系统交互,所以它们的页(Page)大小都为操作系统页大小的整数倍。比如,Oracle的Page大小为8KB。

MySQL程序是跑在Linux操作系统上的,理所当然要跟操作系统交互,所以MySQL中一页数据刷到磁盘,要写4个文件系统里的页。

需要注意的是,这个刷页的操作并非原子操作,比如我操作系统写到第二个页的时候,Linux机器断电了,这时候就会出现问题了。造成「页数据损坏」。并且这种页数据损坏靠 redo日志是无法修复的。

redo重做日志中记录的是对页的物理操作,而不是页面的全量记录,当发生「Partial Page Write(部分页写入)」问题时,出现问题的是未修改过的数据,此时redo日志无能为力。

如何解决Linux机器断电,刷页到一半机器奔溃的问题

Doublewrite Buffer的出现就是为了解决上面的这种情况,给InnoDB存储引擎提供了数据页的可靠性,虽然名字带了Buffer,但实际上Doublewrite Buffer是「内存+磁盘」的结构。

  • 1、内存结构:Doublewrite Buffer内存结构由128个页(Page)构成,大小是2MB。
  • 2、磁盘结构:Doublewrite Buffer磁盘结构在系统表空间上是128个页(2个区,extend1和extend2),大小是2MB。

Doublewrite Buffer的原理是,再把数据页写到数据文件之前,InnoDB先把它们写到一个叫「doublewrite buffer(双写缓冲区)」的共享表空间内,在写doublewrite buffer完成后,InnoDB才会把页写到数据文件适当的位置。

如果在写页的过程中发生意外崩溃,InnoDB会在doublewrite buffer中找到完好的page副本用于恢复。

doublewrite buffer原理

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

1、页数据先通过memcpy函数拷贝至内存中的Doublewrite Buffer中。

2、Doublewrite Buffer的内存里的数据页,会fsync刷到Doublewrite Buffer的磁盘上,分两次写入磁盘共享表空间中(连续存储,顺序写,性能很高),每次写1MB。

3、Doublewrite Buffer的内存里的数据页,再刷到数据磁盘存储.ibd文件上(离散写)。

如果操作系统在将页写入磁盘的过程中发生了崩溃,在恢复过程中,InnoDB存储引擎可以从共享表空间中的Double write中找到该页的一个副本,将其复制到表空间文件,再应用redo日志。

所以在正常的情况下,MySQL写数据页时,会写两遍到磁盘上,第一遍是写到doublewrite buffer,第二遍是写到真正的数据文件中,这便是「Doublewrite」的由来。

我们可以通过如下命令来监控Doublewrite Buffer工作负载,该命令用于显示有关双写缓冲区(doublewrite buffer)的统计信息。‘%dblwr%’ 是一个通配符,匹配所有包含 ‘dblwr’ 的状态变量。

show global status like '%dblwr%';

输出

| Variable_name          | Value |
+------------------------+-------+
| Innodb_dblwr_writes    | 1000  |
| Innodb_dblwr_pages_written | 8000  |

Doublewrite Buffer和redo log

在MySQL的InnoDB存储引擎中,Redo log和Doublewrite Buffer共同工作以确保数据的持久性和恢复能力。

1、当有一个DML(如INSERT、UPDATE)操作发生时, InnoDB会首先将这个操作写入redo log(内存)。这些日志被称为未检查点(uncheckpointed)的redo日志。

2、然后,在修改内存中相应的数据页之前,需要将这些更改记录在磁盘上。但是直接把这些修改的页写到其真正的位置可能会因发生故障导致页部分更新,从而导致数据不一致。因此,InnoDB的做法是先将这些修改的页按顺序写入doublewrite buffer。这就是为什么叫做 “doublewrite” —— 数据实际上被写了两次,先在doublewrite buffer,然后在它们真正的位置。

3、一旦这些页被安全地写入doublewrite buffer,它们就可以按原始的顺序写回到文件系统中。即使这个过程在写回数据时发生故障,我们仍然可以从doublewrite buffer中恢复数据。

4、最后,当事务提交时,相关联的redo log会被写入磁盘。这样即使系统崩溃,redo log也可以用来重播(replay)事务并恢复数据库。

在系统恢复期间,InnoDB会检查doublewrite buffer,并尝试从中恢复损坏的数据页。如果doublewrite buffer中的数据是完整的,那么InnoDB就会用doublewrite buffer中的数据来更新损坏的页。否则,如果doublewrite buffer中的数据不完整,InnoDB也有可能丢弃buffer内容,重新执行那条redo log以尝试恢复数据。

所以,Redo log和Doublewrite Buffer的协作可以确保数据的完整性和持久性。如果在写入过程中发生故障,我们可以从doublewrite buffer中恢复数据,并通过redo log来进行事务的重播。

Doublewrite Buffer相关参数

  • innodb_doublewrite:这个参数用于启用或禁用双写缓冲区。设置为1时启用,设置为0时禁用, 默认值为1。
  • innodb_doublewrite_files:这个参数定义了多少个双写文件被使用。默认值为2,有效范围从2到127。
  • innodb_doublewrite_dir:这个参数指定了存储双写缓冲文件的目录的路径。默认为空字符串,表示将文件存储在数据目录中。
  • innodb_doublewrite_batch_size: 这个参数定义了每次批处理操作写入的字节数。默认值为0,表示InnoDB会选择最佳的批量大小。
  • innodb_doublewrite_pages:这个参数定义了每个双写文件包含多少页面。默认值为128。

总结

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

相关文章

  • 优化 MySQL 3 个简单的小调整

    优化 MySQL 3 个简单的小调整

    本文给大家带来了优化 MySQL 3 个简单的小调整,需要的朋友参考下
    2018-02-02
  • mysql使用insert into select插入查出的数据

    mysql使用insert into select插入查出的数据

    这篇文章主要介绍了mysql使用insert into select插入查出的数据方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • MySQL查看和优化数据库实例详细信息的命令

    MySQL查看和优化数据库实例详细信息的命令

    本文详细介绍了如何查看 MySQL 数据库实例的信息,包括基本信息、配置参数、运行进程和性能监控等方面,通过多个代码示例,读者可以掌握查看和管理数据库实例的具体操作,这些方法和工具对于数据库管理和维护非常重要,可以帮助我们确保数据库的健康运行
    2024-05-05
  • mysql7.x单独安装mysql的方法

    mysql7.x单独安装mysql的方法

    这篇文章主要介绍了mysql7.x单独安装mysql的方法,要解决这个问题,我们要先下载mysql的repo源,具体操作步骤大家通过本文学习吧
    2017-01-01
  • MySql 5.6.14 Win32位免安装解压缩版配置教程

    MySql 5.6.14 Win32位免安装解压缩版配置教程

    本文给大家介绍mysql 5.6.14 win32 位免安装解压缩版配置方法,本文分步骤给大家介绍的非常详细,具有一定的参考借鉴价值,对mysql5.6.14 免安装解压缩版配置方法感兴趣的朋友一起看看吧
    2016-11-11
  • 从零开始搭建MySQL MMM架构

    从零开始搭建MySQL MMM架构

    这篇文章主要介绍了从零开始搭建MySQL MMM架构,本文讲解了配置MySQL Relication、新建同步数据库需要的用户、同步主从数据库、安装MMM、配置MMM、启动MMM等问题,需要的朋友可以参考下
    2015-04-04
  • 将MySQL的表数据全量导入clichhouse库中

    将MySQL的表数据全量导入clichhouse库中

    这篇文章主要介绍了将MySQL的表数据全量导入clichhouse库中,详细介绍全量导出MySQL数据到clickhouse表的相关内容,需要的小伙伴可以参考一下
    2022-03-03
  • linux环境下配置mysql5.6支持IPV6连接的方法

    linux环境下配置mysql5.6支持IPV6连接的方法

    本文主要介绍在linux系统下,如何配置mysql支持IPV6的连接,本文图文并茂给大家介绍的非常详细,具有参考借鉴价值,需要的朋友参考下吧
    2018-01-01
  • MySQL中数据导入恢复的简单教程

    MySQL中数据导入恢复的简单教程

    这篇文章主要介绍了MySQL中数据导入恢复的简单教程,主要用到了LOAD DATA语句,需要的朋友可以参考下
    2015-05-05
  • mysql中ALTER COLLATION使用场景

    mysql中ALTER COLLATION使用场景

    ALTER COLLATION是SQL中用于修改字符集排序规则的操作,本文主要介绍了mysql中ALTER COLLATION使用场景,具有一定的参考价值,感兴趣的可以了解一下
    2025-05-05

最新评论