Chinaunix首页 | 论坛 | 博客
  • 博客访问: 809701
  • 博文数量: 50
  • 博客积分: 757
  • 博客等级: 上士
  • 技术积分: 1913
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-29 14:29
个人简介

DBA

文章分类

全部博文(50)

文章存档

2015年(3)

2014年(2)

2013年(14)

2012年(19)

2011年(12)

分类: Mysql/postgreSQL

2012-02-02 20:59:04

    本文转自    感谢作者

    本文将试图从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编译)

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

  6. #include "stdlib.h" /* for exit */
  7. #include "unistd.h" /* for write fdatasync*/
  8. #include "fcntl.h" /* for open */
  9. int main(void){
  10.     int fd;
  11.     if((fd=open("/home/zzx/test.file",O_WRONLY|O_APPEND|O_DSYNC))<0){
  12.         exit(1);
  13.         }
  14.         char buff[]="abcdef";
  15.         if(write(fd,buff,6)!= 6){
  16.                 exit(2);
  17.         }
  18.         if(fdatasync(fd)==-1){
  19.                 exit(3);
  20.         }
  21.         exit(0);
  22. }

程序描述了一般的文件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.ibm.com/developerworks/cn/linux/l-cn-read/
  5. 系统调用: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)级别?

(全文完)

阅读(2039) | 评论(0) | 转发(0) |
0

上一篇:Vmware IP设置

下一篇:Mongo复制集搭建

给主人留下些什么吧!~~