《The Art of InnoDB》第二部分|第4章:深入结构-磁盘结构-撕裂的页面(doublewrite buffer)

news2024/11/16 9:34:21

4.5 撕裂的页面

目录

4.5 撕裂的页面

4.5.1 双写缓冲区的作用

4.5.2 双写缓冲区的结构

4.5.3 双写缓冲区与Redolog的协同工作流程

4.5.2 双写缓冲区写入时机

4.5.3 禁用双写缓冲区

4.5.4 小结

未完待续...


        上文我们学习了redo log的结构和其工作原理,它是一个记录物理逻辑的日志,描述了数据库记录的逻辑变化,用于崩溃恢复。但是读者是否进一步想过:从数据库层到硬件层还有操作系统层,每一层操作数据读写的最小颗粒都存在差异,所以就会导致一个问题,当数据库正在将一个数据页从缓冲池(buffer pool)写入磁盘时,如果在这个过程中发生崩溃(如操作系统崩溃或硬件故障),可能会导致只有这个页的一部分被写入。这就是所谓的部分写入,它会破坏页的完整性,从而导致数据损坏。那么怎么办呢?

4.5.1 双写缓冲区的作用

        为了解决这个问题,InnoDB引入了双写缓冲区。用来加强数据完整性和恢复能力。其核心目的是防止在数据库崩溃时出现部分写入,也就是说,当数据库正在写入一个页到磁盘,但因为崩溃导致操作只完成了一部分,这个页可能会损坏。它的出现避免了这种情况的发生。从逻辑上来讲,双写缓冲区可以分为两个主要部分:内存中的双写缓冲区和磁盘上的双写缓冲区。

  1. 内存中的双写缓冲区: 在内存中,双写缓冲区不是一个单独的结构,而是缓冲池(Buffer Pool)的一部分。当页被修改,它们变成脏页并存储在缓冲池中。在这些页被写回磁盘之前,页的副本会被创建并存储在内存的双写区域。这样做是为了在写入操作期间如果发生崩溃,可以从双写缓冲区中的副本恢复数据。
  2. 磁盘上的双写缓冲区: 在磁盘上,双写缓冲区是共享表空间(例如ibdata1文件)中的一个特定区域。逻辑上,它被分成两个部分,每一部分足够容纳一定数量的连续InnoDB页的副本。磁盘上的双写缓冲区通常是连续的,以减少磁盘I/O操作的开销。

当InnoDB需要将缓冲池中的脏页刷新到磁盘时,它会执行以下步骤:

  • 写入双写缓冲区: InnoDB首先将脏页的副本写入内存中的双写结构,然后再将这些内存中的副本写入磁盘上的双写缓冲区。
  • 写入最终位置: 一旦磁盘上的双写缓冲区包含了脏页的副本,InnoDB会将这些页从双写缓冲区写入它们在磁盘上的最终位置,即相应的表空间文件(.ibd文件)。

在发生崩溃并随后的恢复过程中,InnoDB会检查双写缓冲区和表空间文件中页的版本。如果表空间文件中的页因为崩溃而损坏,InnoDB会使用双写缓冲区中的副本来恢复这个页。双写缓冲区的设计确保了即使在崩溃发生时也能够恢复所有已提交修改的数据页,防止了部分提交的发生,维护了数据的完整性。

读到这里读者应该会有一个疑问?

1、为什么在内存中和磁盘中都有双写缓冲区?

主要是为了减少磁盘 I/O 操作

  • 直接写入磁盘可能涉及多次随机 I/O,这在性能上是非常昂贵的。通过先将数据写入 doublewrite buffer(在内存中),然后统一刷新到磁盘,可以减少磁盘的随机访问,转而利用顺序写入的高效性。顺序写入通常比随机写入快得多。
  • 同时如果一个脏页在短时间内多次更新,它可能会先写入内存中的 doublewrite buffer,然后再统一刷新到磁盘的 doublewrite 区域。这种做法可以合并对同一数据页的多次写入,从而减少磁盘写入次数。

4.5.2 双写缓冲区的结构

        InnoDB双写缓冲区通常位于系统表空间文件(如ibdata1)内的一个固定区域。逻辑上,它被分为两个部分,每部分可以存储一定数量的页副本。磁盘上的双写缓冲区通常位于共享表空间文件(例如ibdata1)中。它的大小足以存储两个InnoDB数据块。

下图是一个简化的逻辑表示,并不代表双写缓冲区的物理存储的准确布局,旨在帮助读者更好的理解双写缓冲区的概念。

每个数据块包含128个页。由于InnoDB页的默认大小是16KB,每个部分的大小是128 * 16KB = 2MB,因此,其总大小通常为:

2 (块) * 128 (页/块) * 16KB (页大小) = 4MB

需要注意的是,双写缓冲区的大小是不可配置的。它是InnoDB内部决定的一个固定值,为了在系统崩溃时能够恢复被部分写入的页而设计。虽然它确保了数据的持久性和一致性,但它也增加了额外的磁盘I/O,因此可能会稍微影响数据库的写入性能。

当InnoDB需要将脏页刷新到磁盘时,这些页的副本会先写入双写缓冲区的一个部分,然后再写入相应的表空间文件。如果在写入表空间文件时发生崩溃,InnoDB可以使用双写缓冲区中的副本来恢复这些页。


4.5.3 双写缓冲区与Redolog的协同工作流程

        下图描述了一个事务提交 + 刷脏,redolog 和 doublewrite buffer 协同工作的流程,帮助读者理解它们是如何配合工作的。

以下是每个步骤的详细描述:

  1. 事务开始,修改数据: 用户发起一个事务,进行数据修改操作,这会导致数据页被加载到内存(如果不在内存中)并进行修改,这些修改后的页称为“脏页”。
  2. 记录重做日志到Redo Log Buffer: InnoDB将事务修改的操作转换为重做日志记录,并将这些记录存放到内存中的重做日志缓冲区(Redo Log Buffer)。这些记录精确地描述了如何重做(redo)或回滚(undo)每个修改。
  3. 事务提交,刷新Redo Log Buffer到重做日志文件: 当事务提交时,InnoDB确保将Redo Log Buffer中的所有重做日志记录刷新到磁盘上的重做日志文件(通常是两个或更多的文件循环使用)。这个步骤是关键的,因为它确保了即使在系统崩溃之后,所有已提交事务的修改都已经安全地记录到磁盘上。
  4. 写入内存中的双写缓冲区副本: 在脏页被刷新到磁盘之前,InnoDB会先将它们的副本写入到内存中的双写缓冲区。这是为了预防在将脏页写入磁盘表空间文件的过程中发生部分页写入。
  5. 将双写缓冲区副本写入磁盘上的双写缓冲区: 然后,InnoDB将内存中双写缓冲区的副本写入到磁盘上的双写缓冲区。这个磁盘上的双写缓冲区位于共享表空间文件(如ibdata1)中的一个固定位置。
  6. 从双写缓冲区写入表空间文件: 最终,InnoDB会将这些页从双写缓冲区复制到磁盘上的表空间文件中,也就是他们的最终存储位置。这是数据持久化的最后一步。

通过这个流程,双写缓冲区和重做日志共同确保了即使在系统崩溃的情况下,也能够恢复到最后已知的一致状态。重做日志记录了事务的所有变更,这样即使脏页还没来得及写入磁盘,这些变更也不会丢失。双写缓冲区则保护了数据页不会因为部分写入而损坏,从而确保了数据的完整性。这些机制是InnoDB提供的ACID事务属性中的一致性(Consistency)和持久性(Durability)的关键部分。

在这里读者可能会产生一些疑问?

1、Doublewrite buffer 写操作是原子的吗?

写入双写缓冲区的操作本身并不是原子的,但InnoDB采用了一些技术手段来保证如果在双写过程中发生崩溃,数据页仍然可以安全地恢复。如果在 Doublewrite buffer 写入过程中发生崩溃:

重启后InnoDB通过检查数据页的LSN和重做日志来判断是否部分写入发生

  • 正常情况:如果双写缓冲区中的数据页副本完好,InnoDB会使用这些副本来恢复那些可能已损坏的数据页。
  • 异常情况:如果崩溃发生在 Doublewrite buffer 的写入过程中,检查出写入的页是损坏的,因为它既包含旧的数据,也包含新的数据。那么在恢复过程中,InnoDB会使用页的旧副本,也就是磁盘上的原始页(如果之前已经写入)实际上代表了旧版本的数据。如果在双写缓冲区写入过程中发生部分写入,旧版本的数据页仍然保持不变,因此不会立即损坏。

总的来说,双写缓冲区相当于在未刷脏前同时存在两份磁盘页数据,一新(缓冲区数据)一旧(磁盘原有数据),由此来保证在任何情况下都有一份完整的页数据可以供数据恢复使用。并和redolog一起保证了数据的完整性和一致性。

2、如果redolog写入了,但是双写缓冲区中的页副本还未写入,这时候崩溃了怎么办?

如果重做日志(redo log)已经写入磁盘,但双写缓冲区(doublewrite buffer)中的页副本还未写入磁盘时发生了崩溃,InnoDB恢复机制可以确保数据的一致性和完整性。以下是恢复过程的简要说明:

  1. 启动恢复过程: 当InnoDB数据库重启后,它会启动一个自动恢复过程,检查重做日志文件中的日志序列号(LSN)来确定崩溃发生时最后已知的一致状态。
  2. 重放重做日志: InnoDB将遍历重做日志,重放所有在崩溃前已提交的事务。对于那些已经写入到重做日志但尚未刷新到数据页的更改,这些更改会被应用到对应的数据页中。这个步骤确保了所有在崩溃前提交的事务都得到了恢复。
  3. 检查数据页: 如果在重放过程中,重做日志指示某个数据页已经被修改,但是双写缓冲区和表空间文件中的相应页尚未被更新(因为崩溃发生在双写缓冲区将页副本写入磁盘之前),InnoDB会将重做日志中的修改应用到内存中的页副本上。
  4. 应用未完成的更改: 由于重做日志已经被写入,即使双写缓冲区中的页副本尚未被安全写入磁盘,InnoDB也能够使用重做日志中的信息来更新任何需要更新的数据页。

在这个过程中,双写缓冲区用于防止在页写入操作过程中发生的部分写入问题,而重做日志确保所有提交的事务都能在崩溃后恢复到最后一致的状态。即便双写缓冲区中的页副本尚未写入磁盘,重做日志仍然能够提供足够的信息来重建数据页,并确保数据的正确性。因此,即使在上述情况下发生崩溃,InnoDB的恢复过程能够保证数据页的完整性和事务的持久性,这是由于重做日志记录了足够的信息来重构数据页的状态。


4.5.2 双写缓冲区写入时机

        通过以上介绍可以看出,双写缓冲区的工作通常发生在刷脏过程中,脏页通常会在如下几个阶段刷盘,所以双写缓冲区的写入通常也发生在如下场景中:

  1. 检查点发生时: 在执行检查点(checkpoint)操作时,InnoDB会将缓冲池中的脏页写入到磁盘。检查点是确保所有在某一时间点之前的修改都已经被写入到磁盘的过程。
  2. 事务提交: 当事务提交时,所有相关的脏页最终都需要被刷新到磁盘上。不过,并不是在事务提交的那一刻立即写入双写缓冲区,因为提交时脏页可能已经在之前的操作中写入过了。而是在提交过程中,任何因为提交而标记为需要刷新的脏页,在刷新到磁盘前会使用双写缓冲区。

4.5.3 禁用双写缓冲区

        在某些特定场景中,如果系统的磁盘子系统能够确保页的原子写入(atomic write),例如使用某些类型的RAID或电池支持的写入缓存,那么双写缓冲区可能不是必须的。在这些情况下,可以通过MySQL配置参数来禁用双写缓冲区,从而减少I/O开销。然而,在大多数情况下,推荐保持双写缓冲区启用,以确保数据的安全。

        InnoDB的双写缓冲区(Doublewrite Buffer)可以通过MySQL配置文件(my.cnf 或 my.ini)来开启或关闭。要禁用双写缓冲区,你需要在[mysqld]部分设置innodb_doublewrite为0。以下是如何禁用双写缓冲区的示例:

innodb_doublewrite = 0

若要启用双写缓冲区(通常是默认设置),则需要将innodb_doublewrite设置为1:

innodb_doublewrite = 1

修改配置文件后,为了使更改生效,你需要重新启动MySQL服务。

        在禁用双写缓冲区之前,你需要确保你完全了解这样做的风险。双写缓冲区是一种重要的数据完整性保护机制,用于防止在系统崩溃时发生的部分写入错误。禁用它可能会提高性能,但同时也增加了数据损坏的风险。在某些情况下,当你使用的存储设备(如某些类型的SSD)提供自己的原子写入保护机制时,禁用双写缓冲区可能是安全的。然而,在大多数情况下,为了确保数据安全,建议保留双写缓冲区的默认启用状态。


4.5.4 小结

        通过本节的学习,读者应该对InnoDB的双写缓冲区有了深入的理解,包括其在维护数据库完整性和提升系统可靠性方面的关键作用,以及它在整个InnoDB架构中的位置和重要性。同时,也应该意识到在考虑性能优化时需要在数据安全和性能之间做出权衡。

双写缓冲区的目的

  • 防止数据页损坏:双写缓冲区的主要目的是防止在系统崩溃时由于部分写入操作造成的数据页损坏。
  • 数据完整性:双写缓冲区是InnoDB保证数据页在崩溃时不损坏的关键部分,从而维护数据完整性。
  • 系统可靠性:通过提供数据页的完整副本,双写缓冲区提高了整个数据库系统的可靠性。

双写缓冲区的位置

  • 内存中的双写缓冲区:作为性能优化机制,减少磁盘I/O,提高数据写入效率。
  • 磁盘上的双写缓冲区:确保数据页在系统崩溃时能从一个完整的副本中恢复,提供数据持久性。

双写缓冲区的工作流程

  • 脏页处理:当页被修改后,它们被标记为脏页并最终需要被刷新到磁盘。
  • 写入双写缓冲区:在写入数据页到最终位置之前,首先将其副本写入内存中的双写缓冲区,然后刷新到磁盘上的双写缓冲区。
  • 与重做日志协同工作:双写缓冲区与重做日志(Redo Log)一同确保了数据的一致性和完整性。即使在重做日志已经写入而双写缓冲区还未完成写入时发生崩溃,InnoDB的恢复机制也能够保证数据的一致性。

性能与数据安全性的权衡

  • 禁用双写缓冲区:在特定条件下,系统管理员可能会考虑禁用双写缓冲区以提高性能,但这会牺牲数据安全性。
  • 权衡考量:在考虑性能优化时,需要在系统的数据安全和性能之间进行权衡。

        本节阐述了InnoDB双写缓冲区的存在目的和工作机制,通过理解双写缓冲区如何在保证数据完整性和系统可靠性方面发挥作用,读者可以获得关于缓存策略设计的重要知识,进而运用到自己的系统设计中去。


未完待续...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1468754.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue+nodejs+uniapp婚纱定制婚庆摄影系统 微信小程序 springboot+python

目前移动互联网大行其道,人人都手中拿着智能机,手机手机,手不离机,如果开发一个用在手机上的程序软件,那是多么的符合潮流,符合管理者和客户的理想。本次就是开发婚庆摄影小程序,有管理员&#…

LeetCode 2476.二叉搜索树最近节点查询:中序遍历 + 二分查找

【LetMeFly】2476.二叉搜索树最近节点查询:中序遍历 二分查找 力扣题目链接:https://leetcode.cn/problems/closest-nodes-queries-in-a-binary-search-tree/ 给你一个 二叉搜索树 的根节点 root ,和一个由正整数组成、长度为 n 的数组 qu…

Java中的常量与变量:初探Java世界的基石

✨✨ 所属专栏: Java基石:深入探索Java核心基础✨✨ 🎈🎈作者主页: 喔的嘛呀🎈🎈 目录 引言 一. 常量与变量的概念 常量 变量 总结 二. 常量的分类 1. 字面常量 2. 常量变量 3. 枚举常量…

设计模式篇---观察者模式

文章目录 概念结构实例总结 概念 观察者模式:定义对象之间的一种一对多的依赖关系,使得每当一个对象状态发生改变时,其他相关依赖对象都得到通知并被自动更新。 观察者模式是使用频率较高的一个模式,它建立了对象与对象之间的依赖…

JavaScript 进阶02

深入对象 构造函数 构造函数是用于创建对象的函数。 <script> //构造函数 构造函数的首字母大写 function Obj(name,age,aaa){this.namenamethis.ageage } //调用函数 const obj1new Obj("小明",4) console.log(obj1) </script> 使用 new 关键字调用…

2023年海南房地产经纪机构备案需要具备哪些条件?

房地产业在海南占有非常重要的地位。 同样&#xff0c;海南也有很多房地产中介机构。 那么&#xff0c;2023年海南房产中介登记证如何办理呢&#xff1f; 海南房产中介注册需要什么条件&#xff1f; 办理海南房产中介机构登记需要提交哪些材料&#xff1f; ……今天博宇会计小编…

Linux系统——Nginx小总结

目录 一、影响用户体验的因素 二、网络连接——Apache/Nginx服务请求过程 三、I/O模型——Input/Output模型 1.同步/异步 2.阻塞/非阻塞 3.同步异步/阻塞非阻塞组合 四、Nginx用法 一、影响用户体验的因素 客户端硬件配置客户端网络速率客户端与服务端距离服务端网络速…

freemarker模板引擎结合node puppeteer库实现html生成图片

效果图&#xff1a; 先看效果图&#xff0c;以下是基于freemarker模板渲染数据&#xff0c;puppeteer加载html中的js及最后图片生成&#xff1a; 背景&#xff1a; 目前为止&#xff0c;后台java根据html模板或者一个网页路径生成图片&#xff0c;都不支持flex布局及最新的c…

前端解析后端返回文件流格式数据

当后端接口返回数据是一个文件流数据时&#xff0c;如下后端返回给我的是一个pdf文件流数据 methods: {gotoPri() {protocolApi().then(res > {this.createPdf(res.data,XXX协议)})},createPdf(res, name) {// Blob构造函数返回一个新的 Blob 对象并指定type类型。let blob …

递归过程详解(Python)

See https://zhuanlan.zhihu.com/p/382721019

嵌入式学习之Linux入门篇——使用VMware创建Unbuntu虚拟机

目录 主机硬件要求 VMware 安装 安装Unbuntu 18.04.6 LTS 新建虚拟机 进入Unbuntu安装环节 主机硬件要求 内存最少16G 硬盘最好分出一个单独的盘&#xff0c;而且最少预留200G&#xff0c;可以使用移动固态操作系统win7/10/11 VMware 安装 版本&#xff1a;VMware Works…

2.1_4 进程通信

文章目录 2.1_4 进程通信&#xff08;一&#xff09;什么是进程间通信&#xff08;二&#xff09;为什么进程通信需要操作系统支持&#xff08;三&#xff09;共享存储&#xff08;四&#xff09;消息传递&#xff08;1&#xff09;直接通信方式&#xff08;2&#xff09;间接通…

【Spring MVC篇】简单案例分析

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring MVC】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、加法计算器二…

system_v

共享内存 创建共享内存 key_t ftok(const char *pathname, int proj_id);使用相同的pathname和proj_id可以得到相同的key_t pathname必须是一个存在的目录 int shmget(key_t key, size_t size, int shmflg);需要使用ftok获取key_t IPC_CREAT——不存在就创建&#xff0c…

鸿蒙DevEco Service开发准备与使用

DevEco低代码是一个基于Serverless和ArkUI的端云一体化低代码开发平台&#xff0c;可通过拖拽式开发&#xff0c;可视化配置构建元服务。打通HarmonyOS云侧与端侧能力&#xff0c;轻松实现HMS Core和AGC Serverless能力的调用。通过与元服务生态、HMS Core、AGC Serverless平台…

论文阅读:Ground-Fusion: A Low-cost Ground SLAM System Robust to Corner Cases

前言 最近看到一篇ICRA2024上的新文章&#xff0c;是关于多传感器融合SLAM的&#xff0c;好像使用了最近几年文章中较火的轮式里程计。感觉这篇文章成果不错&#xff0c;代码和数据集都是开源的&#xff0c;今天仔细读并且翻译一下&#xff0c;理解创新点、感悟研究方向、指导…

政安晨:【机器学习基础】(一)—— 泛化:机器学习的目标

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 简述 泛化是机器学习中的基本概念之一。它指的是通过学习…

ElasticSearch索引数据备份与恢复

索引数据备份 在磁盘创建备份目录并授权 # 创建备份目录 /home/esbackup # 授权 chmod 777 /home/esbackup修改配置文件elasticsearch.yml echo path.repo: ["/home/esbackup"] >> /etc/elasticsearch/elasticsearch.yml重启elasticsearch(我是docker创建的…

嵌入式按键处理驱动(easy_button)

简介 在嵌入式裸机开发中&#xff0c;经常有按键的管理需求&#xff0c;GitHub上已经有蛮多成熟的按键驱动了&#xff0c;但是由于这样那样的问题&#xff0c;最终还是自己实现了一套。本项目地址&#xff1a;bobwenstudy/easy_button (github.com)。 项目开发过程中参考了如…

了解 JavaScript 中的重放攻击和复现攻击

在网络安全领域&#xff0c;重放攻击&#xff08;Replay Attack&#xff09;和复现攻击&#xff08;Playback Attack&#xff09;是一些可能导致安全漏洞的攻击形式。这两种攻击类型涉及在通信过程中再次发送已经捕获的数据&#xff0c;以达到欺骗系统的目的。本文将介绍 JavaS…