您当前的位置:首页 > 电脑百科 > 数据库 > MYSQL

深入解析 MySQL 双写缓冲区

时间:2023-10-06 12:57:26  来源:微信公众号  作者:Java随想录

在数据库系统的世界中,保障数据的完整性和稳定性是至关重要的任务。为了实现这一目标,MySQL内部使用了许多精巧而高效的机制。

InnoDB是MySQL中一种常用的事务性存储引擎,它具有很多优秀的特性。其中,Doublewrite Buffer是InnoDB的一个重要特性之一,本文将介绍Doublewrite Buffer的原理和应用,帮助读者深入理解其如何提高MySQL的数据可靠性并防止可能的数据损坏。

为什么需要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日志无能为力。

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

内存结构:Doublewrite Buffer内存结构由128个页(Page)构成,大小是2MB。

磁盘结构: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相关参数

以下是一些与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。

总结

Doublewrite Buffer是InnoDB的一个重要特性,用于保证MySQL数据的可靠性和一致性。

它的实现原理是通过将要写入磁盘的数据先写入到Doublewrite Buffer中的内存缓存区域,然后再写入到磁盘的两个不同位置,来避免由于磁盘损坏等因素导致数据丢失或不一致的问题。

总的来说,Doublewrite Buffer对于改善数据库性能和数据完整性起着至关重要的作用。尽管其引入了一些开销,但在大多数情况下,这些成本都被其提供的安全性和可靠性所抵消。



Tags:MySQL   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  Search: MySQL  点击:(5)  评论:(0)  加入收藏
MySQL 核心模块揭秘,你看明白了吗?
为了提升分配 undo 段的效率,事务提交过程中,InnoDB 会缓存一些 undo 段。只要同时满足两个条件,insert undo 段或 update undo 段就能被缓存。1. 关于缓存 undo 段为了提升分...【详细内容】
2024-03-27  Search: MySQL  点击:(10)  评论:(0)  加入收藏
MySQL:BUG导致DDL语句无谓的索引重建
对于5.7.23之前的版本在评估类似DDL操作的时候需要谨慎,可能评估为瞬间操作,但是实际上线的时候跑了很久,这个就容易导致超过维护窗口,甚至更大的故障。一、问题模拟使用5.7.22...【详细内容】
2024-03-26  Search: MySQL  点击:(8)  评论:(0)  加入收藏
从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
ByteHouse是一款OLAP引擎,具备查询效率高的特点,在硬件需求上相对较低,且具有良好的水平扩展性,如果数据量进一步增长,可以通过增加服务器数量来提升处理能力。本文将从兴趣圈层...【详细内容】
2024-03-22  Search: MySQL  点击:(23)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-03-10  Search: MySQL  点击:(5)  评论:(0)  加入收藏
准线上事故之MySQL优化器索引选错
1 背景最近组里来了许多新的小伙伴,大家在一起聊聊技术,有小兄弟提到了MySQL的优化器的内部策略,想起了之前在公司出现的一个线上问题,今天借着这个机会,在这里分享下过程和结论...【详细内容】
2024-03-07  Search: MySQL  点击:(26)  评论:(0)  加入收藏
MySQL数据恢复,你会吗?
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要...【详细内容】
2024-02-22  Search: MySQL  点击:(43)  评论:(0)  加入收藏
如何在MySQL中实现数据的版本管理和回滚操作?
实现数据的版本管理和回滚操作在MySQL中可以通过以下几种方式实现,包括使用事务、备份恢复、日志和版本控制工具等。下面将详细介绍这些方法。1.使用事务:MySQL支持事务操作,可...【详细内容】
2024-02-20  Search: MySQL  点击:(51)  评论:(0)  加入收藏
为什么高性能场景选用Postgres SQL 而不是 MySQL
一、 数据库简介 TLDR;1.1 MySQL MySQL声称自己是最流行的开源数据库,它属于最流行的RDBMS (Relational Database Management System,关系数据库管理系统)应用软件之一。LAMP...【详细内容】
2024-02-19  Search: MySQL  点击:(37)  评论:(0)  加入收藏
MySQL数据库如何生成分组排序的序号
经常进行数据分析的小伙伴经常会需要生成序号或进行数据分组排序并生成序号。在MySQL8.0中可以使用窗口函数来实现,可以参考历史文章有了这些函数,统计分析事半功倍进行了解。...【详细内容】
2024-01-30  Search: MySQL  点击:(53)  评论:(0)  加入收藏
▌简易百科推荐
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  爱可生开源社区    Tags:MySQL   点击:(5)  评论:(0)  加入收藏
MySQL 核心模块揭秘,你看明白了吗?
为了提升分配 undo 段的效率,事务提交过程中,InnoDB 会缓存一些 undo 段。只要同时满足两个条件,insert undo 段或 update undo 段就能被缓存。1. 关于缓存 undo 段为了提升分...【详细内容】
2024-03-27  爱可生开源社区  微信公众号  Tags:MySQL   点击:(10)  评论:(0)  加入收藏
MySQL:BUG导致DDL语句无谓的索引重建
对于5.7.23之前的版本在评估类似DDL操作的时候需要谨慎,可能评估为瞬间操作,但是实际上线的时候跑了很久,这个就容易导致超过维护窗口,甚至更大的故障。一、问题模拟使用5.7.22...【详细内容】
2024-03-26  MySQL学习  微信公众号  Tags:MySQL   点击:(8)  评论:(0)  加入收藏
从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
ByteHouse是一款OLAP引擎,具备查询效率高的特点,在硬件需求上相对较低,且具有良好的水平扩展性,如果数据量进一步增长,可以通过增加服务器数量来提升处理能力。本文将从兴趣圈层...【详细内容】
2024-03-22  字节跳动技术团队    Tags:ByteHouse   点击:(23)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-03-10    dbaplus社群  Tags:MySQL   点击:(5)  评论:(0)  加入收藏
准线上事故之MySQL优化器索引选错
1 背景最近组里来了许多新的小伙伴,大家在一起聊聊技术,有小兄弟提到了MySQL的优化器的内部策略,想起了之前在公司出现的一个线上问题,今天借着这个机会,在这里分享下过程和结论...【详细内容】
2024-03-07  转转技术  微信公众号  Tags:MySQL   点击:(26)  评论:(0)  加入收藏
MySQL数据恢复,你会吗?
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要...【详细内容】
2024-02-22  数据库干货铺  微信公众号  Tags:MySQL   点击:(43)  评论:(0)  加入收藏
如何在MySQL中实现数据的版本管理和回滚操作?
实现数据的版本管理和回滚操作在MySQL中可以通过以下几种方式实现,包括使用事务、备份恢复、日志和版本控制工具等。下面将详细介绍这些方法。1.使用事务:MySQL支持事务操作,可...【详细内容】
2024-02-20  编程技术汇    Tags:MySQL   点击:(51)  评论:(0)  加入收藏
MySQL数据库如何生成分组排序的序号
经常进行数据分析的小伙伴经常会需要生成序号或进行数据分组排序并生成序号。在MySQL8.0中可以使用窗口函数来实现,可以参考历史文章有了这些函数,统计分析事半功倍进行了解。...【详细内容】
2024-01-30  数据库干货铺  微信公众号  Tags:MySQL   点击:(53)  评论:(0)  加入收藏
mysql索引失效的场景
MySQL中索引失效是指数据库查询时无法有效利用索引,这可能导致查询性能显著下降。以下是一些常见的MySQL索引失效的场景:1.使用非前导列进行查询: 假设有一个复合索引 (A, B)。...【详细内容】
2024-01-15  小王爱编程  今日头条  Tags:mysql索引   点击:(82)  评论:(0)  加入收藏
站内最新
站内热门
站内头条