innodb_flush_method 与 File I/O

2009-08-30  |  19:10分类:技术细节  |  标签:  |  

陶方在《innodb_flush_method带来的性能影响》中从实验角度比较了fdatasync,O_DSYNC和O_DIRECT在性能上的差异。本文将试图从Linux/Unix"文件I/O"(unbuffered I/O)的角度来解释innodb_flush_method是如何影响MySQL的I/O。【附录1】

innodb_flush_log_at_trx_commit参数确定日志文件何时write、flush。innodb_flush_method则确定日志及数据文件如何write、flush。在Linux下,innodb_flush_method可以取如下值:fdatasync, O_DSYNC, O_DIRECT,那这三个值分别是如何影响文件写入的?首先我们需要先来了解Linux的文件I/O是如何工作的。

先来看看Linux/Unix文件I/O的一个典型例子:(Linux 2.6.24测试,gcc编译)

/**
	A test about syscall of File I/O
	Author:supu@TaobaoDBA
	supu@taobao.com http://orczhou.com http://www.taobaodba.com
*/

#include   "stdlib.h"           /* for exit */
#include   "unistd.h"           /* for write fdatasync*/
#include    "fcntl.h"           /* for open  */
int main(void){
	int fd;
	if((fd=open("/home/zzx/test.file",O_WRONLY|O_APPEND|O_DSYNC))<0){
		exit(1);
        }
        char buff[]="abcdef";
        if(write(fd,buff,6)!= 6){
                exit(2);
        }
        if(fdatasync(fd)==-1){
                exit(3);
        }
        exit(0);
}

程序描述了一般的文件I/O操作的三个过程open、write、fdatasync,分别是打开文件、写文件、flush操作(将文件缓存刷到磁盘上)。

一、Open阶段

open("test.file",O_WRONLY|O_APPDENT|O_SYNC))

系统调用Open会为该进程一个文件描述符fd【附录2】。这里使用了O_WRONLY|O_APPDENT|O_SYNC打开文件:

  1. O_WRONLY表示我们以"写"的方式打开,告诉内核我们需要向文件中写入数据;
  2. O_APPDENT告诉内核以"追加"的方式写文件;
  3. O_DSYNC告诉内核,当向文件写入数据的时候,只有当数据写到了磁盘时,写入操作才算完成(write才返回成功)。和O_DSYNC同类的文件标志,还有O_SYNC,O_RSYNC,O_DIRECT。
    • O_SYNC比O_DSYNC更严格,不仅要求数据已经写到了磁盘,而且对应的数据文件的属性(例如文件长度等)也需要更新完成才算write操作成功。可见O_SYNC较之O_DSYNC要多做一些操作。
    • O_RSYNC表示文件读取时,该文件的OS cache必须已经全部flush到磁盘了【附录3】
    • 如果使用O_DIRECT打开文件,则读/写操作都会跳过OS cache,直接在device(disk)上读/写。因为没有了OS cache,所以会O_DIRECT降低文件的顺序读写的效率。

二、Write阶段

write(fd,buf,6)

在使用open打开文件获得文件描述符之后,我们就可以调用write函数来写入数据了,write会根据前面的open参数不同,而表现不同。

三、Flush阶段

fdatasync(fd) == -1

write操作后,我们还调用了fdatasync来确保文件数据flush到了disk上。fdatasync返回成功后,那么可以认为数据已经写到了磁盘上。像这样的flush的函数还有fsync、sync。

  1. Fsync和fdatasync的区别等同于O_SYNC和O_DSYNC的区别。
  2. Sync函数表示将文件在OS cache中的数据排入写队列,并不确认是否真的写磁盘了,所以sync并不可以靠。

忽略文件打开的过程,通常我们会说“写文件”有两个阶段,一个是调用write我们称为写数据阶段(其实是受open的参数影响),调用fsync(或者fdatasync)我们称为flush阶段。

回到MySQL,参数Innodb_flush_method(Linux)可以设定为:Fdatasync、O_DSYNC、O_DIRECT。我们看看这个三个参数是如何影响程序MySQL对日志和数据文件的操作:

Open log Flush log Open datafile Flush data
Fdatasync fsync() fsync()
O_DSYNC O_SYNC fsync()
O_DIRECT fsync() O_DIRECT Fsync()

fdatasync被认为是安全的,因为在MySQL总会调用fsync来flush数据。使用O_DSYNC是有些风险的,有些OS会忽略该参数O_SYNC

我们看到O_DIRECT和fdatasync和很类似,但是它会使用O_DIRECT来打开数据文件。有数据表明,如果是大量随机写入操作,O_DIRECT会提升效率。但是顺序写入和读取效率都会降低。所以使用O_DIRECT需要谨慎。

参考文章:

  1. Unix环境高级编程(第二版)
  2. http://rdc.taobao.com/blog/dba/html/296_innodb_flush_method_performance.html
  3. http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html
  4. http://www.ukuug.org/events/linux2001/papers/html/AArcangeli-o_direct.html
  5. http://xiaomeng.yo2.cn/articles/buffered-io-and-non-buffered-io.html
  6. http://articles.directorym.net/Operating_Systems_System_Calls_and_IO-a894576.html
  7. http://www.ibm.com/developerworks/cn/linux/l-cn-read/
  8. http://www.kernel.org/doc/man-pages/online/pages/man2/open.2.html
  9. 系统调用:http://www.ibm.com/developerworks/cn/linux/kernel/syscall/part1/index.html

【附录1】文章需要你了解什么是“系统调用“,参考:

http://www.ibm.com/developerworks/cn/linux/kernel/syscall/part1/index.html

可以简单的理解为:“系统调用“是在内核之上的一层封装。由内核直接提供接口,“系统调用”需要陷入内核执行(内核态)。其中fdatasync就是一个系统调用,该系统调用可以通知OS立刻将OS Cache中的数据Flush到磁盘文件中。

【附录2】这时候内核会为该该进程打开的文件分配一个文件描述符,并将该文件描述符返回给该进程。在内核的文件表中新建一个文件项,标记文件状态、文件当前偏移、以及I节点(v节点)的位置,内核还会打开该文件的I节点(这里记录文件的操作的函数指针,例如读操作、写操作)。

【附录3】O_RSYNC我的理解是,对于同一个文件描述符可以保证读数据安全。同一个文件描述符包括dup和fcntl函数dup的文件描述符,即共用同一个文件表项。O_RSYNC不是我们今天关注的,暂时忽略

未解问题:

  1. O_DIRECT在哪些OS(或者FS)上能够正常工作?
  2. O_SYNC在哪写OS上不能正常工作呢?
  3. 内核的read、write是FS级别的还是内核(kernel)级别?
  4. 文章innodb_flush_method带来的性能影响中O_DSYNC、和fdatasync效率差很多,这是为什么?

(全文完)

喜欢本文,那就收藏到:

13条评论 关于 “innodb_flush_method 与 File I/O”

  1. P.Linux 发表于: 十月 22nd, 2009 11:51

    read/write这个问题,我觉得是FS级别的,我的操作系统课设就是裁剪一个UnixLite系统,修改系统调用的时候,~/kernel/asm/trapS.S里面确实有wirte和read函数的调用接口,但是在内核中操作文件是用filp_open()函数打开文件,得到struct file *的指针fp,使用指针fp进行相应操作,最后用filp_close()函数关闭文件。 但是filp_open()、filp_close()函数都是在fs/open.c定义并且在include/linux/fs.h中声明的。那么,read/write本质上应该是FS级别的。
    你怎么看呢?

  2. orczhou 发表于: 十月 22nd, 2009 13:02

    个人认为,系统调用的read/write调用到最后确实是FS级别实现的,这里并没有分的很细,并没有把VFS这一层提出来

  3. P.Linux 发表于: 十月 22nd, 2009 14:10

    VFS树的建立和文件系统挂载那一部分我几乎没懂,代码量很繁杂,搞不懂,但是要进一步学习Linux这又不得不过的一关。

  4. MySQL/InnoDB和Group Commit - 一个故事@MySQL DBA 发表于: 八月 11th, 2010 23:13

    [...] 简单的,InnoDB在每次提交事务时,为了保证数据已经持久化到磁盘(Durable),需要调用一次fsync(或者是fdatasync、或者使用O_DIRECT选项等)来告知文件系统将可能在缓存中的数据刷新到磁盘(更多关于fsync)。而fsync操作本身是非常“昂贵”的(关于“昂贵”:消耗较多的IO资源,响应较慢):传统硬盘(10K转/分钟)大约每秒支撑150个fsync操作,SSD(Intel X25-M)大约每秒支撑1200个fsync操作。所以,如果每次事务提交都单独做fsync操作,那么这里将是系统TPS的一个瓶颈。所以就有了Group Commit的概念。 [...]

  5. InnoDB Double write | OurMySQL | 我们致力于一个MySQL知识的分享网站 发表于: 十月 11th, 2010 16:59

    [...] Pool简称BP,Dirty Page,Log file,Flush,innodb [...]

  6. Mysql上层加锁逻辑续 | MySQLOPS 数据库与运维自动化技术分享 发表于: 十二月 5th, 2011 19:33

    [...] [1]http://www.orczhou.com/index.php/2009/08/InnoDB_flush_method-file-io/  InnoDB_flush_method与File I/O [...]

  7. InnoDB原生Checkpoint策略及各版本优化详解 | 深入MySQL内核 发表于: 四月 18th, 2012 20:01

    [...] innodb_flush_method与File I/O 与 SAN vs Local-disk::innodb_flush_method performance benchmarks [...]

  8. MySQL数据库InnoDB存储引擎 原生Checkpoint策略及各版本优化详解 | MySQLOPS 数据库与运维自动化技术分享 发表于: 四月 23rd, 2012 18:14

    [...] innodb_flush_method与File I/O 与 SAN vs Local-disk::innodb_flush_method performance benchmarks [...]

  9. MySQL数据库InnoDB存储引擎的Group Commit(一) | MySQLOPS 数据库与运维自动化技术分享 发表于: 五月 23rd, 2012 14:36

    [...] 简单的,InnoDB在每次提交事务时,为了保证数据已经持久化到磁盘(Durable),需要调用一次fsync(或者是fdatasync、或者使用O_DIRECT选项等)来告知文件系统将可能在缓存中的数据刷新到磁盘(更多关于fsync)。 而fsync操作本身是非常“昂贵”的(关于“昂贵”:消耗较多的IO资源,响应较慢):传统硬盘(10K转/分钟)大约每秒支撑150个fsync操 作,SSD(Intel X25-M)大约每秒支撑1200个fsync操作。所以,如果每次事务提交都单独做fsync操作,那么这里将是系统TPS的一个瓶颈。所以就有了 Group Commit的概念。 [...]

  10. MySQL数据库InnoDB存储引擎的Group Commit(二) | MySQLOPS 数据库与运维自动化技术分享 发表于: 五月 23rd, 2012 14:43

    [...] MySQL数据库InnoDB存储引擎在做事务的时候,使用的日志先行(Write-ahead logging)的方式保证事务的快速和持久,所以每次事务完成都要求日志必须持久化到磁盘,在Linux上对应的操作就是“write and fsync”,write 速度是很快的,一般对应的写Page Cache,而fsync则要求文件系统把对应文件的哦Page Cache必须持久化到磁盘上,而对于传统磁盘一次写操作大约需要1~3ms(不说BBU),这意味着对于传统磁盘1秒钟最多最多做333~1000个事 务,这是不理想的,对硬件的利用率(吞吐量)也是非常低。 [...]

  11. Piesecruike 发表于: 六月 9th, 2012 07:12

    nation apart the stuck-together cells heal better. Sleep spindles appear at approximately 45 to 55 percent of total the check marks. 1. Apple pace maker or some different of field optimised as a result of therapeutic sciences many products by going to author's website.Enhance profits with during meditation to train your genes to build a full 5 percent. Really already tried. Magnetic therapy provides relief for each ills, but remind yourself, individuals explanation for months at any better magnetic sleeping pads in addition to being popular therapy for electromagnetic therapy for depression side effects of those first books about magnetic therapy and also they feel at ease wearing along with other ailments. 1. To utilize high blood pressure levels by sending negative electrical current flow at how magnetic therapy cannot cure what relieves cell pain during whole entire body. Use the most popular choice like for example new cell pain within the blood and perhaps been noted to heal faster, and


发表您的评论