innodb为什么需要doublewrite(转)
InnoDB的page size默认是16KB,而操作系统的一个block size是4KB,磁盘io block则更小。那么InnoDB的page刷到磁盘上要写4个操作系统block,在极端情况下(比如断电)不一定能保证4个块的写入原子性,假如只有一部分写是成功的,那么innodb的数据page就不是一个完整的page(break page),这种现象称为partial write。
innodb怎么解决partial write?
innodb采用的是doublewrite机制,在写数据page时,会写两遍到磁盘上,第一遍是写到doublewrite buffer(实际上是共享表空间的一块区域),第二遍是从doublewrite buffer写到真正的数据文件中。如果发生了partial write,InnoDB再次启动后就可以从doublewrite buffer中进行page的恢复。由于第一遍page落盘与第二遍page落盘在不同的时间点,所以不会出现doublewrite page和数据page同时发生partial write的情况。
innodb为什么不用redo log来恢复break page?
redo log的页大小一般设计为512个字节,因此redo log page本身不会发生break page。用redo log来解决partial write 理论上是可行的,不过innodb的redo log是逻辑物理日志(不做展开),并不是物理日志,因此发生partial write后崩溃恢复过程中不能直接应用redo log ,innodb发现break page后实际上会报错。
innodb能否通过其他方式解决partial write?
可以,如果系统表空间文件(“ibdata文件”)位于支持原子写入的Fusion-io设备上,就能避免partial write ,可以不用doublewrite机制。还有大名鼎鼎的阿里云polardb,在底层分布式文件系统PolarFS能提供页大小(如16)KB小的原子写入,无需double write 机制来避免partial write。还有XDB的DBFS也类似实现了原子写。
可以总结数据库为了解决partial write问题,一般有4种手段:
- 事后恢复:innodb doublewirite 机制,事先存一份page的副本,当partial write发生需要恢复时,先通过page的副本来还原该page,再进行重做;
- 事后恢复:物理redo log 恢复机制,物理redo log里面存有完整的数据page,当partial write发生需要恢复时,先通过redo log page的副本来还原该page,再进行重做可以保证幂等性;
- 事先避免:底层存储来实现原子写入避免partial write;
- 事先避免:数据库的page size 设置为块设备扇区大小512字节保证原子写避免partial write,如:innodb redo log 。
下面来看下常见的存储引擎或者数据库系统他们是怎么解决partial write的。
PostgreSQL
PG采用的是第二种方式。通过full_page_write机制,在物理redo log中写dirty page的full page解决了数据页的partial write问题。然而pg的redo log page size默认是8K的,不是512字节对齐物理磁盘block,所以理论上PG的redo log 也会存在partial write。不过redo log 的partial write并不会带来数据一致性的问题,因为假如出现了partial write说明事务未提交成功,那么崩溃恢复的时候对PG来说也是不会去恢复的。
MongoDB WiredTiger
WiredTiger中刷脏页是通过将内存中的btree修改过的PAGE做一次checkpoint并写入持久化存储,每个btree对应磁盘上一个物理文件,btree的每个PAGE以文件里的extent形式上的page。很显然checkpoint是一个append only方式,也就是说WiredTiger会保存多个checkpoint版本。由于原page并没有被更新,所以即使发生partial write,不管从哪个版本的checkpoint开始都可以通过重演journal log恢复来保证page的完整性。值得一提的是MongoDB 3.5.12中WiredTiger在内存和journal log中实现了in-place update,但数据写磁盘的机制并未改变,因此依然可以解决partial write。
RocksDB & InfluxDB
存储引擎采用LSM或者TSM(类LSM)的结构,数据page采用append only方式写入,而不是像innodb或PG一样采用in-place update的方式写入page,所以即使出现了partial write,由于原page没有变更,可以通过原page重做wal log恢复来保证page的完整性。
innodb为什么需要doublewrite(转)的更多相关文章
- MySQL Doublewrite Buffer及业务评估
1. 关于Doublewrite Buffe的总结 Doublewrite Buffer:Doublewrite Buffer出现的初衷是防止buffer pool中的脏页刷新到磁盘中,出现部分写的问 ...
- Mysql Innodb体系结构
Innodb体系结构 Innodb存储引擎主要包括内存池以及后台线程. 内存池:多个内存块组成一个内存池,主要维护进程/线程的内部数据.缓存磁盘数据,修改文件前先修改内存.redo log 后台线程: ...
- Innodb 状态的部分解释
Innodb_buffer_pool_pages_data Innodb buffer pool缓存池中包含数据的页的数目,包括脏页.单位是page. Innodb_buffer_pool_pages ...
- 《Mysql技术内幕,Innodb存储引擎》——Innodb体系结构
Innodb体系结构 Innodb存储引擎主要包括内存池以及后台线程. 内存池:多个内存块组成一个内存池,主要维护进程/线程的内部数据.缓存磁盘数据,修改文件前先修改内存.redo log 后台线程: ...
- mysql 异常宕机 ..InnoDB: Database page corruption on disk or a failed,,InnoDB: file read of page 8.
mysql 测试环境异常宕机 系统:\nKylin 3.3 mysql版本:5.6.15--yum安装,麒麟提供的yum源数据库版本 error日志 181218 09:38:52 mysqld_sa ...
- Innodb整体架构
如下图展示了Innodb内存中和磁盘的结构: 内存中结构主要有如下几种: buffer pool change buffer adaptive hash index (自适应的hash索引) Log ...
- 【3.4】innodb存储引擎
[1]Innodb 与 Myisam 的区别 1.InnoDB支持事物,而MyISAM不支持事物 2.InnoDB支持行级锁,而MyISAM支持表级锁 3.InnoDB支持MVCC, 而MyISAM不 ...
- 【InnoDB】插入缓存,两次写,自适应hash索引
InnoDB存储引擎的关键特性包括插入缓冲.两次写(double write).自适应哈希索引(adaptive hash index).这些特性为InnoDB存储引擎带来了更好的性能和更高的可靠性. ...
- innodb状态
Innodb_buffer_pool_pages_data Innodb buffer pool缓存池中包含数据的页的数目,包括脏页.单位是page. Innodb_buffer_pool_pages ...
随机推荐
- 原生JS实现下拉列表
1 <div class="list"> 2 <ul> 3 <li> 4 <a href="#">Web部< ...
- day34 Pyhton 网络编程
一今日内容 # 函数 # 面向对象 # 进阶 # 网络编程 4 # 并发编程 6-7 # 概念 # 网络基础 # 局域网的概念 # 交换机和路由器的工作流程 # ip地址 # mac地址 # 子网掩码 ...
- SpringBoot+MongoDB实现物流订单系统
码字不易,点赞收藏,养成习惯!原创作者公众号:bigsai.更多精彩期待与您分享!项目收录在github的MongoDB案例中,文章收录在回车课堂中如果没基础请看看前两篇(墙裂推荐)MongoDB从立 ...
- Linux发行版教你如何选 给入门者的选择通法
Linux的发行版何止琳琅满目,简直是乱入你眼. 本篇将介绍选择发行版的经验和通用法则,主要会从PC角度去谈. 更新于2020年,初次发布于2017年 选择发行版需考虑哪些因素 选择发行版时需要考虑的 ...
- centos8安装RabbitMQ
一.安装erlang # 添加仓库 curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh ...
- VMware虚拟机中共享文件夹 开机启动
输入命令: sudo /usr/bin/vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other -o uid=1000 -o gid=1000 -o umask=02 ...
- Gitlab 11.9.1 高可用教程
Gitlab 11.9.1 高可用教程 一. PostgreSQL数据迁移 由于默认Gitlab的安装会内置Postgres数据库,并且没有对外,所以我们需要通过设置对应的Gitlab的配置将其中的数 ...
- Python字典的初识、增删改查及嵌套
为什么要有字典? 列表可以存储大量的数据,但数据间的关联型不强 列表的查询速度相对慢 dict:字典,容器型数据类型 数据类型的分类: 可变与不可变 可变(不可哈希)的数据类型: 列表list,字典d ...
- 使用creata-react-app脚手架创建react项目时非常慢的问题
创建react项目必须要有下面两个步骤 cnpm install -g create-react-app //创建react全局变量 create-react-app my-app //创建一个re ...
- Lombda表达式(四)
/* * 自定义函数式接口: * 1.声明一个接口,只能包含一个抽象方法 * 2.给这个接口加@FunctionalInterface */ public class Test { public st ...