12

innodb_flush_method 与 Linux File I/O

 3 years ago
source link: https://blogread.cn/it/article/213?f=hot1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

innodb_flush_method 与 Linux File I/O

浏览:2803次  出处信息

    陶方在《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编译)

<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#fdfddf"><p><font style="FONT-WEIGHT: bold; COLOR: #990000">以下是代码片段:</font></p><p>/**<br> A test about syscall of File I/O<br> Author:supu@TaobaoDBA<br> <a href="mailto:[email protected]">[email protected]</a> <a href="http://www.taobaodba.com">http://www.taobaodba.com</a><br>*/</p><p>#include   "stdlib.h"           /* for exit */<br>#include   "unistd.h"           /* for write fdatasync*/<br>#include    "fcntl.h"           /* for open  */<br>int main(void){<br> int fd;<br> if((fd=open("/home/zzx/test.file",O_WRONLY|O_APPEND|O_DSYNC))<0){<br>  exit(1);<br>        }<br>        char buff[]="abcdef";<br>        if(write(fd,buff,6)!= 6){<br>                exit(2);<br>        }<br>        if(fdatasync(fd)==-1){<br>                exit(3);<br>        }<br>        exit(0);<br>}</p></td></tr></tbody></table>

    程序描述了一般的文件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打开文件:

O_WRONLY表示我们以”写”的方式打开,告诉内核我们需要向文件中写入数据;O_APPDENT告诉内核以”追加”的方式写文件;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。

Fsync和fdatasync的区别等同于O_SYNC和O_DSYNC的区别。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 dataFdatasync

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需要谨慎。

    参考文章:

Unix环境高级编程(第二版)http://rdc.taobao.com/blog/dba/html/296_innodb_flush_method_performance.htmlhttp://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.htmlhttp://www.ukuug.org/events/linux2001/papers/html/AArcangeli-o_direct.htmlhttp://xiaomeng.yo2.cn/articles/buffered-io-and-non-buffered-io.htmlhttp://articles.directorym.net/Operating_Systems_System_Calls_and_IO-a894576.htmlhttp://www.ibm.com/developerworks/cn/linux/l-cn-read/http://www.kernel.org/doc/man-pages/online/pages/man2/open.2.html系统调用: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不是我们今天关注的,暂时忽略

    未解问题:

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

    (全文完)

觉得文章有用?立即:

和朋友一起 共学习 共进步!

建议继续学习:

QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK