细看InnoDB数据落盘

数据从InnoDB的内存到真正写到存储设备的介质上到底有哪些缓冲在起作用。

我们通过下图看一下相关的缓冲:


image.png

从上图中,我们可以看到,数据InnoDB到磁盘需要经过

  1. InnoDB buffer pool, Redo log buffer。这个是InnoDB应用系统本身的缓冲。
  2. page cache /Buffer cache(可通过o_direct绕过)。这个是vfs层的缓冲。
  3. Inode cache/directory buffer。这个也是vfs层的缓冲。需要通过O_SYNC或者fsync()来刷新。
  4. Write-Back buffer。(可设置存储控制器参数绕过)
  5. Disk on-borad buffer。(可通过设置磁盘控制器参数绕过)

2. InnoDB层

该层的缓冲都放在主机内存中,它的目的主要是在应用层管理自己的数据,避免慢速的读写操作影响了InnoDB的响应时间。

InnoDB层主要包括两个buffer:redo log buffer和innodb buffer pool。redo log buffer用来暂存对重做日志redo log的日志写,InnoDB buffer pool存储了从磁盘设备读到的InnoDB数据,也缓冲了对InnoDB数据写,即脏页数据。如果主机掉电或者MySQL异常宕机,innodb buffer pool将无法及时刷新到磁盘,那么InnoDB就只能从上一个checkpoint使用redo log来前滚;而redo log buffer如果不能及时刷新到磁盘,那么由于redo log中数据的丢失,就算使用redo 前滚,用户提交的事务由于没有真正的记录到非易失型的磁盘介质中,就丢失掉了。

控制redo log buffer刷新时机的参数是innodb_flush_log_at_trx_commit,而控制redo log buffer和innodb buffer pool刷新方式的参数为innodb_flush_method。针对这两个参数详细介绍的文章有非常多,我们这里主要从缓冲的角度来解析。

2.1. innodb_flush_log_at_trx_commit
控制redo log buffer的innodb_flush_log_at_trx_commit目前支持3种不同的参数值0,1,2

2.2. innodb_flush_method
控制innodb buffer pool的innodb_flush_method目前支持4种不同的参数值:

  • fdatasync
  • O_DSYNC
  • O_DIRECT
  • O_DIRECT_NO_FSYNC

这里我们注意到有几个问题:

  1. innodb_flush_method指定的不仅是“数据文件”的刷新方式,也指定了“日志文件”刷新方式。

  2. 这些参数里面没有在windows环境下的参数配置,现在大家都开始不鸟盖茨兄了?其实在注释里面写了,windows就使用async_unbuffered,并且不允许修改,所以没有写到列表里面。

  3. 前三个参数值只允许在6.6和5.6.6之前的版本中用,从5.6.7开始新增了O_DIRECT_NO_FSYNC。也就是说用O_DIRECT打开文件,但是不用fsync()同步数据。这个由于在较新的Linux内核和部分文件系统中,使用O_DIRECT就可以保证数据安全,不用专门再用fsync()来同步,保证元数据也刷新到非易失型的磁盘介质。例如:XFS就不能用这个参数。O_DIRECT绕过了page cache,为什么还要用fsync()再刷新以下,我们在下节专门讨论。

如果指定O_DIRECT,O_DIRECT_NO_FSYNC,数据文件是以O_DIRECT打开(solaris上用directio()方式打开,如果Innodb的数据文件都放在单独的设备时,可以在mount 时使用forcedirectio使得整个文件系统都是以directio打开。这里指明为innodb而不是MySQL的原因是,MyISAM不要用directio())

image.png

3. VFS层

该层的缓冲都放在主机内存中,它的目的主要是在操作系统层缓冲数据,避免慢速块设备读写操作影响了IO的响应时间。

3.1. 细究O_DIRECT/O_SYNC标签
在前面redo log buffer和innodb buffer pool的讨论中涉及到很多数据刷新和数据安全的问题,我们在本节中,专门讨论O_DIRECT/O_SYNC标签的含义。

我们打开一个文件并写入数据,VFS和文件系统是怎么把数据写到硬件层列,下图展示了关键的数据结构:

image.png

图中,我们看到该层中主要有page_cache/buffer cache/Inode-cache/Directory cache。其中page_cache/buffer cache主要用于缓冲内存结构数据和块设备数据。而inode-cache用于缓冲inode,directory-cache用于缓冲目录结构数据。

根据文件系统和操作系统的不同,一般来说对一个文件的写入操作包括两部分,对数据本身的写入操作,以及对文件属性(metadata元数据)的写入操作(这里的文件属性包括目录,inode等)。

了解了这些以后,我们就能够比较简单的说清楚各个标志的意义了:


image.png
  • O_DSYNC和fdatasync()的区别在于:是在每一个IO提交的时刻都针对对应的page cache和buffer cache进行刷新;还是在一定数据的写操作以后调用fdatasync()的时刻对整个page cache和buffer cache进行刷新。O_SYNC和fsync()的区别同理。
  • page cache和buffer cache的主要区别在于一个是面向实际文件数据,一个是面向块设备。在VFS上层使用open()方式打开那些使用mkfs做成文件系统的文件,你就会用到page cache和buffer cache,而如果你在Linux操作系统上使用dd这种方式来操作Linux的块设备,你就只会用到buffer cache。
  • O_DSYNC和O_SYNC的区别在于:O_DSYNC告诉内核,当向文件写入数据的时候,只有当数据写到了磁盘时,写入操作才算完成(write才返回成功)。O_SYNC比O_DSYNC更严格,不仅要求数据已经写到了磁盘,而且对应的数据文件的属性(例如文件inode,相关的目录变化等)也需要更新完成才算write操作成功。可见O_SYNC较之O_DSYNC要多做一些操作。
  • Open()的referense中还有一个O_ASYNC,它主要用于terminals, pseudoterminals, sockets, 和pipes/FIFOs,是信号驱动的IO,当设备可读写时发送一个信号(SIGIO),应用进程捕获这个信号来进行IO操作。
  • O_SYNC和O_DIRECT都是同步写,也就是说只有写成功了才会返回。

回过头来,我们再来看innodb_flush_log_at_trx_commit的配置就比较好理解了。O_DIRECT直接IO绕过了page cache/buffer cache以后为什么还需要fsync()了,就是为了把directory cache和inode cache元数据也刷新到存储设备上。

而由于内核和文件系统的更新,有些文件系统能够保证保证在O_DIRECT方式下不用fsync()同步元数据也不会导致数据安全性问题,所以InnoDB又提供了O_DIRECT_NO_FSYNC的方式。

3.2. O_DIRECT优劣势

在大部分的innodb_flush_method参数值的推荐中都会建议使用O_DIRECT,甚至在percona server分支中还提供了ALL_O_DIRECT,对日志文件也使用了O_DIRECT方式打开。

3.2.1. 优势:

  • 节省操作系统内存:O_DIRECT直接绕过page cache/buffer cache,这样避免InnoDB在读写数据少占用操作系统的内存,把更多的内存留个innodb buffer pool来使用。
  • 节省CPU。另外,内存到存储设备的传输方式主要有poll,中断和DMA方式。使用O_DIRECT方式提示操作系统尽量使用DMA方式来进行存储设备操作,节省CPU。

3.2.2. 劣势

  • 字节对齐。O_DIRECT方式要求写数据时,内存是字节对齐的(对齐的方式根据内核和文件系统的不同而不同)。这就要求数据在写的时候需要有额外的对齐操作。可以通过/sys/block/sda/queue/logical_block_size知道对齐的大小,一般都是512个字节。
  • 无法进行IO合并。O_DIRECT绕过page cache/buffer cache直接写存储设备,这样如果对同一块数据进行重复写就无法在内存中命中,page cache/buffer cache合并写的功能就无法生效了。

总的来说,使用O_DIRECT来设置innodb_flush_method并不是100%对所有应用和场景都是适用的。

小结

从InnoDB到最终的介质,我们经过了各种缓冲,他们的目的其实很明确,就是为了解决:内存和磁盘的速度不匹配的问题,或者说是磁盘的速度过慢的问题。

另外,其实最懂数据是否应该缓冲/缓存的还是应用本身,VFS,存储控制器和磁盘只能通过延迟写入(以便合并重复IO,使随机写变成顺序写)来缓解底层存储设备慢速造成的响应速度慢的问题。所以数据库类型的应用都会来自己管理缓冲,然后尽量避免操作系统和底层设备的缓冲。

但是其实由于目前SSD固态硬盘和PCIe Flash卡的出现,内存和磁盘之间的速度差异被大大缩减了,这些缓冲是否必要,软硬件哪些可改进的,对软硬件工程师的一大挑战

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352