IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

innodb_flush_method 与 Linux File I/O

DBA@Taobao 2009-10-18 23:13:10 累计浏览 4,256 次
本机暂存

    陶方在《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://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打开文件:

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

    参考文章:

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效率差很多,这是为什么?

    (全文完)

同分类推荐文章

  1. 使用deepseek进行Oracle恢复,引起重大故障 (2026-06-22 10:56:00)
  2. 接手一个只差临门一脚的数据库恢复 (2026-06-18 00:13:09)
  3. 我做了一个 AI 版的 StarRocks 升级风险扫描工具,直接帮我定位到一个风险 (2026-06-15 01:00:00)

查看更多 数据库 文章 →

建议继续学习

  1. 用Hyer来进行网站的抓取 (累计阅读 158,252)
  2. MySQL数据库在实际应用一些方面的介绍 (累计阅读 36,399)
  3. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,164)
  4. Mysql监控指南 (累计阅读 21,351)
  5. 由浅入深探究mysql索引结构原理、性能分析与优化 (累计阅读 16,523)
  6. Linux如何统计进程的CPU利用率 (累计阅读 16,308)
  7. 我的 RHCA 之路 (累计阅读 14,013)
  8. Linux内存点滴 用户进程内存空间 (累计阅读 13,232)
  9. 给程序员新手的一些建议 (累计阅读 13,089)
  10. 在Apache2.2.XX下安装Mod-myvhost模块 (累计阅读 13,058)