当前位置: 首页 > article >正文

Double Write

优质博文:IT-BLOG-CN

一、存在的问题

为什么需要Double Write InnoDBPageSize16kb,其数据校验也是针对这16KB来计算的,将数据写入磁盘是以Page为单位的进行操作的。而计算机硬件和操作系统,写文件是以4KB作为基本单位,那么将一个Page写到磁盘上,在OS级别需要4个块。当发生数据库宕机时,并不能保证这一操作的原子性。例如Innodb存储引擎正在写入某个页到表中,而这个页只写了一部分4KB。之后就发生了宕机,这种现象被称为部分写失效partial page write。在Innodb存储引擎未使用doublewrite技术前,曾经出现过因为部分写失效而导致数据丢失的现象,磁盘上是一个不完整的数据页。因为系统恢复后MySQL是不是可以根据 redolog 进行恢复。redolog记录的是物理位置(即变更向量)binlog记录的是逻辑日志(即纯粹的SQL),他们都无法恢复这个数据页的数据,毕竟每一次更改不是改变了整个数据页,而是改变一个数据页的一小部分

下面做一个数据写入过程的大致描述:

当发起一个update,首先需要从os存储.ibd文件中读取对应的数据页到buffer cache中;然后SQL对其进行更改,更改的数据物理位置(位置偏移量)写入redo log;完成日志落盘后buffer刷脏时,需要将buffer中更改的脏数据页dirty page完完整整的写入OS存储中,这里就会出现数据库和OS调用IO次数不同的鸿沟。

脏页: 当数据从磁盘加载到缓冲池的数据页后,数据页内容被修改后,此数据页称为脏页

Insert Buffer是用来提高存储引擎性能上的提升,Double Write就是为了在数据库崩溃恢复时保证数据不丢失的一个重要特性,保证了数据的可靠性。

二、Double Write

自己先想想如何能够解决上述问题,思想很重要。

Double Write的思想就是:给当前的这个Page做一个备份,如果写脏页的时候发生宕机,在重启后使用下备份先恢复下数据页再写磁盘就可以了。

如图,其实Double Write分为了两个组成部分:
【1】内存中的double write buffer
【2】物理磁盘上共享表空间中连续的128个页,即2个区extent,大小同样为2MB

数据库表空间由段segment、区extent、页page组成。
  ■ 段segment:包括了数据段(B+树的叶子结点)、索引段、回滚段。
  ■ 区extent:由连续的页组成,任何情况下每个区都为1M,一个区中有64个连续页16k
  ■ 页page:,数据页B-tree Node默认大小为16KB

使用Double Write后的脏页刷新流程就是多了几步操作:
【1】在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是会通过memcpy函数将脏页先复制到内存中的Double write buffer
【2】通过double write buffer再分两次,每次1MB顺序地写入共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘,避免缓冲写带来的问题

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

共享表空间Doublewrite Buffer中的数据是修改前的数据。在写入数据页到磁盘之前,首先将数据页写入到共享表空间中,然后再将共享表空间中的数据页复制一份写入到磁盘上的数据文件。这个过程中,共享表空间中的数据页保存的是事务执行之前的数据,也就是修改前的数据。这样做的目的是为了保证数据页写入磁盘的原子性。如果在写入数据页到磁盘时发生故障,可以通过共享表空间中的数据页来恢复数据,保证数据的一致性。当发生故障后,需要使用共享表空间的备份来覆盖磁盘上的数据文件,将修改前的数据重新写入到磁盘。然后,通过redo log来进行数据恢复,重新执行事务的修改操作,将修改后的数据写入到磁盘,从而完成数据的恢复。

下面显示了一个由Double write进行恢复的情况:

090923 12:36:32 mysqld restarted
090923 12:26:33 InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.
InnoDB: Reading tablespace information from the .ibd files...
InnoDB: Crash recovery may have faild for some .ibd files!
InnoDB: Restoring possible half-written data pages from the doublewrite.
InnoDB: buffer...

三、Double Write 的问题

Double write buffer它是在物理文件上的一个buffer, 其实也就是file,所以它会导致系统有更多的fsync操作,而因为硬盘的fsync性能问题,所以也会影响到数据库的整体性能。Double write页是连续的,因此这个过程是顺序写的,开销并不是很大。经测试开启DBWinnodb的写入时间仅仅比不开启高10%,为了数据安全方式写丢失,这个代价是可以承受的。

在完成Double write页的写入后,再将Double write buffer中的页写入各个数据文件中,此时的写入则是离散的

如果有double write buffer,会检查double writer的数据的完整性,如果不完整直接丢弃double write buffer内容,重新执行那条redo log,如果double write buffer的数据是完整的,用double writer buffer的数据更新该数据页,跳过该redo log


http://www.kler.cn/news/307662.html

相关文章:

  • ElementUI大坑Notification修改样式
  • 无人机飞行时状态详解!!!
  • KV260 进阶开发(PYNQ驱动开发+Pixel Pack)
  • 哪些网站用python开发
  • AMD EPYC 9004服务器内存配置深度分析:为何全通道填充是关键?
  • [000-01-008].第05节:OpenFeign特性-重试机制
  • 基于51单片机的隧道车辆检测系统
  • MOE论文汇总
  • 【STM32】esp8266连接wifi
  • Zookeeper学习
  • 免费还超快,我用 Cursor 做的“汉语新解”插件开源了
  • C++初阶:STL详解(三)——vector的介绍和使用
  • c#进度条实现方法
  • 使用模拟退火算法进行优化的案例:Python实现与详细介绍
  • 鹏哥C语言24---结构体struct
  • java基础(小技巧)
  • Objects as Points基于中心点的目标检测方法CenterNet—CVPR2019
  • 鸡蛋检测系统源码分享
  • Spring Cloud Gateway中的常见配置
  • Android Framework(六)WMS-窗口显示流程——窗口内容绘制与显示
  • Python 将矩阵转换为行最简形式 (Row Echelon Form, REF)和列最简形式 (Column Echelon Form, CEF)
  • SpringBoot2:web开发常用功能实现及原理解析-上传与下载
  • Python学习笔记--面向对象、类、属性、继承、正则表达式、错误和异常
  • 基于python+django+vue的个性化餐饮管理系统
  • 数据结构——原来二叉树可以这么学?(4.链式二叉树)
  • 使用HTML和CSS制作网页的全面指南
  • Wordpress右下角表单弹出插件
  • 【Gateway】网关服务快速上手
  • 形而上学(Metaphysics)
  • 北京通州自闭症学校推荐:打造和谐学习氛围,助力孩子成长