数据库系统是基于文件系统的,其性能和设备读写的机制有密切的关系。和数据库性能密切相关的文件I/O操作的三个操作:
open 打开文件
write 写文件
fdatasync flush操作(将文件缓存刷到磁盘上)。
一、Open操作
open("test.file",O_WRONLY|O_APPDENT|O_SYNC))
系统调用Open会为该进程一个文件描述符fd。这里使用了O_WRONLY|O_APPDENT|O_SYNC打开文件:
1. O_WRONLY表示我们以"写"的方式打开,告诉内核我们需要向文件中写入数据;
2. O_APPDENT告诉内核以"追加"的方式写文件;
3. O_DSYNC告诉内核,当向文件写入数据的时候,只有当数据写到了磁盘时,写入操作才算完成(write才返回成功)。
4. 和O_DSYNC同类的文件标志,还有O_SYNC,O_RSYNC,O_DIRECT。
(1) O_SYNC比O_DSYNC更严格,不仅要求数据已经写到了磁盘,而且对应的数据文件的属性(例如文件长度等)也需要更新完成才算write操作成功。可见O_SYNC较之O_DSYNC要多做一些操作。
(2) 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阶段。Linux上的块设备的操作可以分为两类:
第一类是使用C标准库中的fopen/fread/fwrite 系列的函数,我们可以称其为 buffered I/O。
具体的I/O path如下:
Application<->Library Buffer<->Operation System Cache<->File System/Volume Manager<->Device
library buffer是标准库提供的用户空间的buffer,可以通过setvbuf改变其大小。
第二类是使用Linux的系统调用的open/read/write 系列的函数,我们可以称其为 non-buffered I/O。
Application<-> Operation System Cache <->File System/Volume Manager<->Device
此外,我们可以通过设置open的O_DIRECT 标志来实现Direct I/O (或者叫Raw I/O ),即绕过OS Cache,直接读取Device ( that's what we want^o^ ), 等于将OS cache换成自己管理的cache。不过,Linus在邮件列表中建议不这么做,而是使用posix_fadvice, madvice。中表明Direct I/O比buffered I/O的性能高很多。
在MySQL中,参数Innodb_flush_method(Linux)可以设定为:Fdatasync、O_DSYNC、O_DIRECT。我们看看这个三个参数是如何影响程序MySQL对日志和数据文件的操作:
Open logFlush logOpen datafileFlush data
Fdatasync
fsync()
fsync()
O_DSYNCO_SYNC
fsync()
O_DIRECT
fsync()O_DIRECTFsync()
fdatasync被认为是安全的,因为在MySQL总会调用fsync来flush数据。 使用O_DSYNC是有些风险的,有些OS会忽略该参数O_SYNC。
我们看到O_DIRECT和fdatasync和很类似,但是它会使用O_DIRECT 来打开数据文件。有数据表明,如果是大量随机写入操作,O_DIRECT 会提升效率。但是顺序写入和读取效率都会降低。所以使用O_DIRECT需要谨慎。
mysql innodb 对应相关参数:
innodb_flush_method有三个值,分别是fdatasync,O_DSYNC和O_DIRECT,其中fdatasync是默认值。
它们控制了InnoDB刷新日志和数据的模式。
fdatasync: InnoDB使用fsync()函数去更新日志和数据文件。
O_DSYNC: InnoDB使用O_SYNC模式打开并更新日志文件,用fsync()函数去更新数据文件。
O_DIRECT: InnoDB使用O_DIRECT模式打开数据文件,用fsync()函数去更新日志和数据文件。
我们看到O_DIRECT和fdatasync和很类似,但是它会使用O_DIRECT 来打开数据文件。有数据表明,如果是大量随机写入操作,O_DIRECT 会提升效率。但是顺序写入和读取效率都会降低。所以使用O_DIRECT需要谨慎。
【
可选取值有Fdatasync, O_DSYNC, O_DIRECT
- *Fdatasync
调用open(“./ib_logfile0”, …),不设置O_SYNC, 但调用fsync()
调用open(“./ibdata1”, …),不设置O_SYNC, 但调用fsync() - *O_DSYNC,
调用open(“./ib_logfile0”, …),设置O_SYNC, 不调用fsync()
调用open(“./ibdata1”, …),不设置O_SYNC,但调用fsync() - *O_DIRECT
调用open(“./ib_logfile0”, …),不设置O_DIRECT, 调用fsync()
调用open(“./ibdata1”, …),设置O_DIRECT,调用fsync()
】
来自it专家网:http://linux.ctocio.com.cn/274/12586274.shtml
MySQL如何避免使用swap
Linux有很多很好的内存、IO调度机制,但是并不会适用于所有场景。对于DBA来说Linux比较让人头疼的一个地方是,它不会因为MySQL很重要就避免将分配给MySQL的地址空间映射到swap上。对于频繁进行读写操作的系统而言,数据看似在内存而实际上在磁盘是非常糟糕的,响应时间的增长很可能直接拖垮整个系统。这篇blog主要讲讲我们作为DBA,怎样尽量避免MySQL惨遭swap的毒手。
首先我们要了解点基础的东西,比如说为什么会产生swap。假设我们的物理内存是16G,swap是4G。如果MySQL本身已经占用了12G物理内存,而同时其他程序或者系统模块又需要6G内存,这时候操作系统就可能把MySQL所拥有的一部分地址空间映射到swap上去。
cp一个大文件,或用mysqldump导出一个很大的数据库的时候,文件系统往往会向Linux申请大量的内存作为cache,一不小心就会导致L使用swap。这个情景比较常见,以下是最简单的三个调整方法:
1、/proc/sys/vm/swappiness的内容改成0(临时),/etc/sysctl.conf上添加vm.swappiness=0(永久)
这个参数决定了Linux是倾向于使用swap,还是倾向于释放文件系统cache。在内存紧张的情况下,数值越低越倾向于释放文件系统cache。
当然,这个参数只能减少使用swap的概率,并不能避免Linux使用swap。
2、修改MySQL的配置参数innodb_flush_method,开启O_DIRECT模式。
这种情况下,InnoDB的buffer pool会直接绕过文件系统cache来访问磁盘,但是redo log依旧会使用文件系统cache。值得注意的是,Redo log是覆写模式的,即使使用了文件系统的cache,也不会占用太多。
3、添加MySQL的配置参数memlock
这个参数会强迫mysqld进程的地址空间一直被锁定在物理内存上,对于os来说是非常霸道的一个要求。必须要用root帐号来启动MySQL才能生效。
还有一个比较复杂的方法,指定MySQL使用大页内存(Large Page)。Linux上的大页内存是不会被换出物理内存的,和memlock有异曲同工之妙。具体的配置方法可以参考:http://harrison-fisk.blogspot.com/2009/01/enabling-innodb-large-pages-on-linux.html
来自:http://www.taobaodba.com/html/552_mysql_avoid_swap.html