MySQL之Double Write Buffer分析

之前有阅读过相关的文档和资料,总归差了点意思,这次抽出时间仔细推敲了一下,把一些结果记录下来;
杨大师的博文给了很大的帮助:http://blog.itpub.net/22664653/viewspace-1140915/
-------------------------------------------------------------------------------------正文------------------------------------------------------------------------------------
Double Write Buffer是什么?
这是一个buffer,存在于内存中,在持久化到磁盘的时候,这一部分数据会写进innodb的表空间里,由一段连续的pages组成
Double Write这个特性,和命名所描述的完全一致:写两遍~

为什么要引入Double Write Buffer?
引入Double Write Buffer是为了解决partial page write的问题,关于这个问题的描述,引用杨大师的原文,
>>>
InnoDB 的Page Size一般是16KB,其数据校验也是针对这16KB来计算的,将数据写入到磁盘是以Page为单位进行操作的。
而计算机硬件和操作系统,在极端情况下(比如断电)往往并不能保证这一操作的原子性,
16K的数据,写入4K 时,发生了系统断电/os crash ,只有一部分写是成功的,这种情况下就是 partial page write 问题。
<<<

追问1:抛开page不完全写入的这个概念,DB在做crash recovery的时候,不是可以从redo log来重新做一遍么,为什么还要这个特性呢?
解答:原因有两个,
1.由于Page的不完全写入,实际上这个出问题的Page由于没有完全写入所以这个page的checksum是无效的,想恢复这个page的时候,无法定位是哪个page写出了问题;
2.redo-log的原因, MySQL的innodb在生成redo-log的时候,并没有写入具体数据的变更,而是只记录了这个变更所在的page信息,具体的格式如下
    [Space-id] [Page-id] [Where-in-the-page-to-modify] [Payload]
其中,space-id记录的是这个信息存储于哪个redo-log文件,page-id记录的就是page的id(..._(:з」∠)_...),其余信息基本如描述所示;
由于redo-log的这种记录方式,使得MySQL不能依靠redo-log去把崩溃前后一段时间的整个事务全部找出来,然后重做;(存都没存数据,怎么恢复╮(╯▽╰)╭

Double Write Buffer工作在哪个阶段/时机?
当innodb从buffer pool中刷新pages到磁盘时,并不是直接往磁盘写,而是先写进这个Double Write Buffer,
然后马上调用fsync(),将这一部分数据写到磁盘上,之后再把这部分的pages写到真正的数据文件里面去;

Double Write Buffer能不能解决问题?
答案肯定是可以~
情景1:innodb从buffer pool往Double Write Buffer写pages的时候,出事故了,发生了page的部分写入;
分析:innodb在crash recovery的时候,检查到数据文件的pages都是正常的,通过比较LSN/checksum能够检查到数据文件的具体状态,然后再去恢复数据;
情景2:Double Write Buffer往真正的数据文件写pages的时候,出事故了,发生了page的部分写入;
分析:由于Double Write Buffer本身有这个pages的完整内容,从Double Write Buffer重新往数据文件写pages即可;

Double Write Buffer对性能的影响?
由于Double Write Buffer本身是一段完全连续的空间,所以Double Write Buffer从内存写到磁盘的时候是完完全全的顺序写
所以对性能的影响并没有从1个fsync()到2个fsync()这么夸张,引用percona的工程师的判断:性能影响不超过5%-10%;

-------------------------------------------------------------------------------------结尾------------------------------------------------------------------------------------
PS:MySQL的crash recovery不仅依靠了redo log,应该还有binlog的功劳在里面,不过这方面了解的不是很清晰,挖个坑,以后推敲......坑坑坑
PPS:新年新气象~博客施工继续~

时间: 2024-10-14 19:57:45

MySQL之Double Write Buffer分析的相关文章

[MySQL 5.6] double write buffer的几个关键函数

一个double write buffer 有2MB, 共128个page,在MySQL 5.6中, 默认有120个page用于批量刷新(如 LRU Flush 或者FLUSH LIST FLUSH),剩下的8个Page用于单个page的flush. 在DEBUG版本下,120是可以通过参数innodb_doublewrite_batch_size来配置的,好吧.我已经不安分的把DEBUG宏给去掉了. 全局对象buf_dblwr, 对应结构体为buf_dblwr_t: ib_mutex_t  m

MySQL · 杂谈 · InnoDB Double Write Buffer 那些事儿

我们知道,由于文件系统对一次大数据页(例如InnoDB的16KB)大多数情况下不是原子操作,这意味着如果服务器宕机了,可能只做了部分写入.在InnoDB看来,这样的数据页是无法通过checksum验证的.即时我们强制让其通过验证,也无法从崩溃中恢复,因为当前InnoDB存在的一些日志类型,有些是逻辑操作,并不能做到幂等. 为了解决这个问题,InnoDB实现了double write buffer,简单来说,就是在写数据页之前,先把这个page写到一块独立的物理文件位置,然后再写到数据页.这样在宕

MySQL · 引擎特性 · InnoDB Buffer Pool

前言 用户对数据库的最基本要求就是能高效的读取和存储数据,但是读写数据都涉及到与低速的设备交互,为了弥补两者之间的速度差异,所有数据库都有缓存池,用来管理相应的数据页,提高数据库的效率,当然也因为引入了这一中间层,数据库对内存的管理变得相对比较复杂.本文主要分析MySQL Buffer Pool的相关技术以及实现原理,源码基于阿里云RDS MySQL 5.6分支,其中部分特性已经开源到AliSQL.Buffer Pool相关的源代码在buf目录下,主要包括LRU List,Flu List,Do

MySQL的double write和Oracle对比学习

之前有网友希望我对mysql的double write和oracle能够做一个对比,其实这种对比方式挺好,能够触类旁通,举一反三.不过限于本人水平有限,欢迎拍砖. 关于MySQL的double write是对partilal write的一个补充.比如将数据写入磁盘的时候,发生了断电情况,那么一部分内容写入一部分就丢失了,这个时候使用redo log来恢复就不可行了,因为从日志文件层面数据的变更已经是不完整的了. double write的大体是这样的.部分内容参考了链接 http://www.

【MySQL】double write 浅析

介绍double write之前我们有必要了解partial page write 问题 :      InnoDB 的Page Size一般是16KB,其数据校验也是针对这16KB来计算的,将数据写入到磁盘是以Page为单位进行操作的.而计算机硬件和操作系统,在极端情况下(比如断电)往往并不能保证这一操作的原子性,16K的数据,写入4K 时,发生了系统断电/os crash ,只有一部分写是成功的,这种情况下就是 partial page write 问题. 很多DBA 会想到系统恢复后,My

[MySQL 源码] 从buffer pool中获取空闲block流程

当我们将一个page读入内存时,需要先为其分配一个block,从buffer pool中获取.入口函数为buf_LRU_get_free_block 之前在http://mysqllover.com/?p=303有简要介绍,这里详细看看,当然,跟最近博客的主题一样,我们还是主要针对压缩表来分析. 以下分析基于Percona Server 5.5.18 buf_LRU_get_free_block loop: 1.block = buf_LRU_get_free_only(buf_pool) 首先

mysql性能优化-慢查询分析、优化索引和配置

目录 一.优化概述 二.查询与索引优化分析 1性能瓶颈定位 Show命令 慢查询日志 explain分析查询 profiling分析查询   2索引及查询优化 三.配置优化 1)      max_connections 2)      back_log 3)      interactive_timeout 4)      key_buffer_size 5)      query_cache_size 6)      record_buffer_size 7)      read_rnd_b

MySQL ORDER BY 的实现分析_Mysql

下面将通过实例分析两种排序实现方式及实现图解:假设有 Table A 和 B 两个表结构分别如下:sky@localhost : example 01:48:21> show create table AG*************************** 1. row ***************************Table: ACreate Table: CREATE TABLE `A` (`c1` int(11) NOT NULL default '0′,`c2` char(2

一个优化MySQL查询操作的具体案例分析_Mysql

问题描述 一个用户反映先线一个SQL语句执行时间慢得无法接受.SQL语句看上去很简单(本文描述中修改了表名和字段名): SELECT count(*) FROM a JOIN b ON a.`S` = b.`S` WHERE a.`L` > '2014-03-30 00:55:00' AND a.`L` < '2014-03-30 01:00:00' ; 且查询需要的字段都建了索引,表结构如下: CREATE TABLE `a` ( `L` timestamp NOT NULL DEFAULT