敲黑板:InnoDB的Double Write,你必须知道
世界上最快的捷径,就是脚踏实地,本文已收录【架构技术专栏】关注这个喜欢分享的地方。
前序
InnoDB引擎有几个重点特性,为其带来了更好的性能和可靠性:
插入缓冲(Insert Buffer)
两次写(Double Write)
自适应哈希索引(Adaptive Hash Index)
异步IO(Async IO)
刷新邻接页(Flush Neighbor Page)
今天我们的主题就是 两次写(Double Write), 先一句话概括下:
上一次我们讲过Insert Buffer 是用来提高存储引擎性能上的提升,Double Write 就是为了在数据库崩溃恢复时保证数据不丢失的一个重要特性,保证了数据的可靠性。
概念点

如图,还是先来说几个基础的概念:
数据库表空间由段(segment)、区(extent)、页(page)组成
默认情况下有一个共享表空间ibdata1,如使用了innodb_file_per_table则每张表独立表空间(指存放数据、索引、插入缓冲bitmap页)
段包括了数据段(B+树的叶子结点)、索引段、回滚段
区,由连续的页组成,任何情况下每个区都为1M,一个区中有64个连续页(16k)
页,数据页(B-tree Node)默认大小为16KB
文件系统一页 默认大小为4KB
盘片被分为许多扇形的区域,每个区域叫一个扇区,硬盘中每个扇区的大小固定为512字节
脏页,当数据从磁盘加载到缓冲池的数据页后,数据页内容被修改后,此数据页称为脏页
出现的问题
通过上次讲的 重要,知识点:InnoDB的插入缓冲 我们知道,脏页会在某些场景下进行刷盘,将缓冲池内的脏页数据落地到磁盘。
因为存储引擎缓冲池内的数据页大小默认为16KB,而文件系统一页大小为4KB,所以在进行刷盘操作时,就有可能发生如下场景:

如图所示,数据库准备刷新脏页时,需要四次IO才能将16KB的数据页刷入磁盘。
但当执行完第二次IO时,数据库发生意外宕机,导致此时才刷了2个文件系统里的页,这种情况被称为写失效(partial page write)。
此时重启后,磁盘上就是不完整的数据页,就算使用redo log也是无法进行恢复的。
注意:
redo log无法恢复数据页损坏的问题,恢复必须是数据页正常并且redo log正常。
这里要知道一点,redo log中记录的是对页的物理操作,如偏移量600,写'xxxx'记录。
如果这个页本身已经发生了损坏,再对其进行重做是没有意义的
该怎么解决这个问题
那应该怎么来解决这个问题呢?其实大家想一下就会有个大概的答案,就是给它搞个备份呗。
如果写脏页的时候发生宕机,在重启后使用下备份先恢复下数据页在写磁盘就可以了,其实这就是Double Write 。
Double Write 出现
千呼万唤始出来,为了防止我们可怜的数据被破坏,InnoDB存储引擎提供了重要的Double Write 特性,避免了数据丢失的惨剧发生。
下面我们来慢慢的来看看Double Write 到底是怎么提高可靠性的
Double Write 解决的问题
在数据库进行脏页刷新时,如果此时宕机,有可能会导致磁盘数据页损坏,丢失我们重要的数据。此时就算重做日志也是无法进行恢复的,因为重做日志记录的是对页的物理修改。
其实就是在重做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是double write。
Double Write 架构

如图,其实Double Write 分为了两个组成部分:
- 内存中的double write buffer
- 物理磁盘上共享表空间中连续的128个页,即2个区(extent),大小同样为2MB
可以看出,有了Double write后的脏页刷新流程就是多了几步操作:
在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是会通过memcpy函数将脏页先复制到内存中的Double write buffer
通过Double write buffer再分两次,每次1MB顺序地写入共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘,避免缓冲写带来的问题
Double write崩溃恢复

如图,如果操作系统在将页写入磁盘的过程中发生了崩溃,在恢复过程中,InnoDB存储引擎可以从共享表空间中的Double write中找到该页的一个副本,将其复制到表空间文件,再应用重做日志。
下面显示了一个由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页是连续的,因此这个过程是顺序写的,开销并不是很大。
在完成Double write页的写入后,再将Double write buffer中的页写入各个数据文件中,此时的写入则是离散的
总结
当commit 一个修改语句时,如果redo log有空闲区域,直接写redo log,如果redo log没有空闲区域,那么需要把被覆盖的redo log对应的数据页刷新到data file 中,最后改pool buffer中的记录
innodb的redo log 不会记录完整的一页数据,因为这样日志太大,它只会记录那次(sequence)如何操作了(update,insert)哪页(page)的哪行(row)
因为数据库使用的页(page,默认16KB)大小和操作系统对磁盘的操作页(page,默认4KB)不一样,当提交了一个页需要刷新到磁盘,会有多次IO, 此时刷了前面的8k时异常发生宕机。在系统恢复正常后,如果没有double write机制,此时数据库磁盘内的数据页已损坏,无法使用redo log进行恢复。
如果有double write buffer,会检查double writer的数据的完整性,如果不完整直接丢弃double write buffer内容,重新执行那条redo log,如果double write buffer的数据是完整的,用double writer buffer的数据更新该数据页,跳过该redo log。

敲黑板:InnoDB的Double Write,你必须知道的更多相关文章
- datatable动态列处理,重绘表格(敲黑板,划重点!!!我肝了一天半才彻底弄懂这个东西,TAT)
datatable动态列处理,重绘表格 前言:至于动态列的绘画,我前面博客已经写过了,就是动态列的配置问题,不懂的去我博客看下,今天要写的呢,就是你已经写了一个动态列在datatable,现在你想重新 ...
- MySQL · 引擎特性 · InnoDB 事务子系统介绍
http://mysql.taobao.org/monthly/2015/12/01/ 前言 在前面几期关于 InnoDB Redo 和 Undo 实现的铺垫后,本节我们从上层的角度来阐述 InnoD ...
- Innodb页面存储结构-2
上一篇<Innodb页面存储结构-1>介绍了Innodb页面存储的总体结构,本文会介绍页面的详细内容,主要包括页头.页尾和记录的详细格式. 学习数据结构时都说程序等于数据结构+算法,而在i ...
- MySQL ·InnoDB 文件系统之文件物理结构
从上层的角度来看,InnoDB层的文件,除了redo日志外,基本上具有相当统一的结构,都是固定block大小,普遍使用的btree结构来管理数据.只是针对不同的block的应用场景会分配不同的页类型. ...
- 前端向后台的华丽转身 — PHP入门篇
三个月就这么悄悄溜走了,本K对于前端虽然有了一定的认识,但对一些方面还是处于一种比较萌币的状态,就在这种萌币状态下,本K又跟着大神浩开始了后台语言-PHP语言的学习.PHP的学习对于学过其他语言的人来 ...
- 整理C++面试题for非CS程序猿——更新至【48】
结合网上的C++面试题+自己的面经,进行整理记录,for我这种非CS的程序猿.(不定期更新,加入了自己的理解,如有不对,请指出) [1] new/delete和malloc/free的区别和联系? 1 ...
- BAT 前端开发面试 —— 吐血总结
更好阅读,请移步这里 聊之前 最近暑期实习招聘已经开始,个人目前参加了腾讯和阿里的内推及百度的实习生招聘,在此总结一下 一是备忘.总结提升,二是希望给大家一些参考 其他面试及基础相关可以参考其他博文: ...
- BigDecimal 类型转换、运算、比较
序:Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数.在实际应用中,需要对更大或者更小的数 ...
- 剑指offer错题记录
错误重点: 1. 传递vector参数时,如果调用函数改变了vector的内容,一定一定要&,传引用保持一致 旋转数组的最小数字:有重复数字情况,二分查找照样搞.情况考虑要周全,当a[mid] ...
随机推荐
- 基于gis的系统开发,程序运行出现问题 ArcGIS product not specified.You must first bind to an ArcGIS version prior to using any ArcGIS components.
在之前初始化的时候添加下面的一行代码:ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop);还需要添加一个引 ...
- gerrit安装配置记录
gerrit安装配置 java -jar gerrit-2.13.5.war init -d gerrit Authentication method [OPEN/?]: htt Install Ve ...
- Python正则表达式 re.sub()函数:标志位flags与参数个数问题
这两天在写爬虫程序,涉及英文文本处理,需要规范化英文标点符号的写法.正常情况下,英文句号「.」后面需要保证有且只有一个空格,但也有例外情况,比如「i.e.」.「e.g.」.「P.S.」这种.由于无法预 ...
- STM32的CCM RAM
STM32F407ZGT6的Flash大小为1MB,SRAM大小为(128KB+64KB). 这里SRAM之所以分开表示是因为在芯片内部前面的128KB和后面的64KB地址不是连续的,后面的64KB在 ...
- 【DFIR】数字取证与事件应急响应---初识
应急响应 适用于负责现场应急,找出可疑的程序,恶意代码的安全工程师.这些可疑恶意程序或代码由另外的专家进行逆向分析. 前言 首先,什么是DRIF? DRIR:Digital Forensics and ...
- 浙大《数据结构》学习&练习(一)算法初步
1.数据结构是数据在计算机中的组织方式,类比图书在图书馆中的存储,应该如何分类,如何在书架上存取. 2.抽象数据结构是对一类的数据的一种组织方式的通用(抽象)描述,包括类型的名称,数据对象集和操作集. ...
- 【SSO】一个简单的单点登录演示实现
业务系统的管理后台往往数量众多,且各自需要一套用户名密码来进行登录,不方便使用.因此花了点时间研究如何实现一套单点登录系统. 众所周知,SSO系统设计中,往往需要想办法解决cookie不能跨域的问题, ...
- 轻轻松松学CSS:Flex布局
Flex布局就是"弹性布局",它可以简便.完整.响应式地实现各种页面布局.引入弹性布局的目的,当页面需要适应不同的屏幕大小确保元素拥有恰当的布局方式,对一个容器中的子元素进行排列 ...
- 安装 Windows 10 系统时分区选择 MBR 还是 GUID?
一.MBR 和 GUID 的概述 MBR 分区表 MBR:Master Boot Record,即硬盘主引导记录分区表,指支持容量在2.1TB以下的硬盘,超过2.1TB的硬盘只能管理2.1TB,最多只 ...
- 【Office-Word妙手回春】Word文本秒转表格
第一步:Ctrl+A组合键,文本全选 第二步:插入→表格→文本转换成表格 第三步:在"文字分隔位置",勾选相应的符号. 此处的分隔符为 空格. 点击"确定"按钮 ...