<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>一个故事@MySQL DBA &#187; File IO</title>
	<atom:link href="http://www.orczhou.com/index.php/tag/file-io/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.orczhou.com</link>
	<description>一个故事@MySQL DBA</description>
	<lastBuildDate>Tue, 20 Dec 2011 15:51:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>innodb_flush_method 与 File I/O</title>
		<link>http://www.orczhou.com/index.php/2009/08/innodb_flush_method-file-io/</link>
		<comments>http://www.orczhou.com/index.php/2009/08/innodb_flush_method-file-io/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 11:10:41 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[技术细节]]></category>
		<category><![CDATA[File IO]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://orczhou.com/?p=693</guid>
		<description><![CDATA[<p>陶方在《<a href="http://rdc.taobao.com/blog/dba/html/296_innodb_flush_method_performance.html">innodb_flush_method带来的性能影响</a>》中从实验角度比较了fdatasync，O_DSYNC和O_DIRECT在性能上的差异。本文将试图从Linux/Unix"文件I/O"（unbuffered I/O）的角度来解释innodb_flush_method是如何影响MySQL的I/O。<sup>【附录1】</sup></p>
<p>innodb_flush_log_at_trx_commit参数确定日志文件<strong><span style="text-decoration: underline;">何时</span></strong>write、flush。innodb_flush_method则确定日志及数据文件<strong><span style="text-decoration: underline;">如何</span></strong>write、flush。在Linux下，innodb_flush_method可以取如下值：fdatasync, O_DSYNC, O_DIRECT，那这三个值分别是如何影响文件写入的？首先我们需要先来了解Linux的文件I/O是如何工作的。<br />
[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2009/08/innodb_flush_method-file-io/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>陶方在《<a href="http://rdc.taobao.com/blog/dba/html/296_innodb_flush_method_performance.html">innodb_flush_method带来的性能影响</a>》中从实验角度比较了fdatasync，O_DSYNC和O_DIRECT在性能上的差异。本文将试图从Linux/Unix"文件I/O"（unbuffered I/O）的角度来解释innodb_flush_method是如何影响MySQL的I/O。<sup>【附录1】</sup></p>
<p>innodb_flush_log_at_trx_commit参数确定日志文件<strong><span style="text-decoration: underline;">何时</span></strong>write、flush。innodb_flush_method则确定日志及数据文件<strong><span style="text-decoration: underline;">如何</span></strong>write、flush。在Linux下，innodb_flush_method可以取如下值：fdatasync, O_DSYNC, O_DIRECT，那这三个值分别是如何影响文件写入的？首先我们需要先来了解Linux的文件I/O是如何工作的。<br />
<span id="more-693"></span><br />
先来看看Linux/Unix文件I/O的一个典型例子：（Linux 2.6.24测试，gcc编译）</p>
<blockquote><pre>
/**
	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))&lt;0){
		exit(1);
        }
        char buff[]="abcdef";
        if(write(fd,buff,6)!= 6){
                exit(2);
        }
        if(fdatasync(fd)==-1){
                exit(3);
        }
        exit(0);
}
</pre>
</blockquote>
<p>程序描述了一般的文件I/O操作的三个过程open、write、fdatasync，分别是打开文件、写文件、flush操作（将文件缓存刷到磁盘上）。</p>
<p style="text-indent:0"><font size=4><b>一、Open阶段</b></font></p>
<blockquote><p>
open("test.file",O_WRONLY|O_APPDENT|O_SYNC))
</p></blockquote>
<p>系统调用Open会为该进程一个文件描述符fd<sup>【附录2】</sup>。这里使用了O_WRONLY|O_APPDENT|O_SYNC打开文件:</p>
<ol>
<li>O_WRONLY表示我们以"写"的方式打开，告诉内核我们需要向文件中写入数据；</li>
<li>O_APPDENT告诉内核以"追加"的方式写文件；</li>
<li>O_DSYNC告诉内核，当向文件写入数据的时候，只有当数据写到了磁盘时，写入操作才算完成（write才返回成功）。和O_DSYNC同类的文件标志，还有O_SYNC,O_RSYNC，O_DIRECT。
<ul>
<li>O_SYNC比O_DSYNC更严格，不仅要求数据已经写到了磁盘，而且对应的数据文件的属性（例如文件长度等）也需要更新完成才算write操作成功。可见O_SYNC较之O_DSYNC要多做一些操作。</li>
<li>O_RSYNC表示文件读取时，该文件的OS cache必须已经全部flush到磁盘了<sup>【附录3】</sup>；</li>
<li>如果使用O_DIRECT打开文件，则读/写操作都会跳过OS cache，直接在device（disk）上读/写。因为没有了OS cache，所以会O_DIRECT降低文件的顺序读写的效率。</li>
</ul>
</li>
</ol>
<p style="text-indent:0"><font size=4><b>二、Write阶段</b></font></p>
<blockquote><p>write(fd,buf,6)</p></blockquote>
<p>在使用open打开文件获得文件描述符之后，我们就可以调用write函数来写入数据了，write会根据前面的open参数不同，而表现不同。</p>
<p style="text-indent:0"><font size=4><b>三、Flush阶段</b></font></p>
<blockquote><p>fdatasync(fd) == -1</p></blockquote>
<p>write操作后，我们还调用了fdatasync来确保文件数据flush到了disk上。fdatasync返回成功后，那么可以认为数据已经写到了磁盘上。像这样的flush的函数还有fsync、sync。</p>
<ol>
<li>Fsync和fdatasync的区别等同于O_SYNC和O_DSYNC的区别。</li>
<li>Sync函数表示将文件在OS cache中的数据排入写队列，并不确认是否真的写磁盘了，所以sync并不可以靠。</li>
</ol>
<p>忽略文件打开的过程，通常我们会说“写文件”有两个阶段，一个是调用write我们称为写数据阶段（其实是受open的参数影响），调用fsync（或者fdatasync）我们称为flush阶段。</p>
<p>回到MySQL，参数Innodb_flush_method(Linux)可以设定为：Fdatasync、O_DSYNC、O_DIRECT。我们看看这个三个参数是如何影响程序MySQL对日志和数据文件的操作：</p>
<style>   
#mytable  td{text-align:center}   
</style>
<table border="1" cellspacing="0" cellpadding="0" BORDERCOLOR="#0000FF">
<tbody id="mytable">
<tr>
<td width="114" valign="top"></td>
<td width="114" valign="top">Open log</td>
<td width="114" valign="top">Flush log</td>
<td width="114" valign="top">Open datafile</td>
<td width="114" valign="top">Flush data</td>
</tr>
<tr>
<td width="114" valign="top">Fdatasync</td>
<td width="114" valign="top"></td>
<td width="114" valign="top"><strong>fsync()</strong></td>
<td width="114" valign="top"></td>
<td width="114" valign="top"><strong>fsync()</strong></td>
</tr>
<tr>
<td width="114" valign="top">O_DSYNC</td>
<td width="114" valign="top"><strong>O_SYNC</strong></td>
<td width="114" valign="top"></td>
<td width="114" valign="top"></td>
<td width="114" valign="top"><strong>fsync()</strong></td>
</tr>
<tr>
<td width="114" valign="top">O_DIRECT</td>
<td width="114" valign="top"></td>
<td width="114" valign="top"><strong>fsync()</strong></td>
<td width="114" valign="top"><code><strong>O_DIRECT</strong></code></td>
<td width="114" valign="top"><strong>Fsync()</strong></td>
</tr>
</tbody>
</table>
<p>fdatasync被认为是安全的，因为在MySQL总会调用fsync来flush数据。使用O_DSYNC是有些风险的，有些OS会忽略该参数<strong>O_SYNC</strong>。</p>
<p>我们看到O_DIRECT和fdatasync和很类似，但是它会使用<code><strong>O_DIRECT</strong></code>来打开数据文件。有数据表明，如果是大量随机写入操作，<code><strong>O_DIRECT</strong></code>会提升效率。但是顺序写入和读取效率都会降低。所以使用O_DIRECT需要谨慎。</p>
<p><strong></strong></p>
<p>参考文章：</p>
<ol>
<li>Unix环境高级编程（第二版）</li>
<li><a href="http://rdc.taobao.com/blog/dba/html/296_innodb_flush_method_performance.html">http://rdc.taobao.com/blog/dba/html/296_innodb_flush_method_performance.html</a></li>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html">http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html</a></li>
<li><a href="http://www.ukuug.org/events/linux2001/papers/html/AArcangeli-o_direct.html">http://www.ukuug.org/events/linux2001/papers/html/AArcangeli-o_direct.html</a></li>
<li><a href="http://xiaomeng.yo2.cn/articles/buffered-io-and-non-buffered-io.html">http://xiaomeng.yo2.cn/articles/buffered-io-and-non-buffered-io.html</a></li>
<li><a href="http://articles.directorym.net/Operating_Systems_System_Calls_and_IO-a894576.html">http://articles.directorym.net/Operating_Systems_System_Calls_and_IO-a894576.html</a></li>
<li><a href="http://www.ibm.com/developerworks/cn/linux/l-cn-read/">http://www.ibm.com/developerworks/cn/linux/l-cn-read/</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/open.2.html">http://www.kernel.org/doc/man-pages/online/pages/man2/open.2.html</a></li>
<li>系统调用：<a href="http://www.ibm.com/developerworks/cn/linux/kernel/syscall/part1/index.html">http://www.ibm.com/developerworks/cn/linux/kernel/syscall/part1/index.html</a></li>
</ol>
<p>【附录1】文章需要你了解什么是“系统调用“，参考：</p>
<p><a href="http://www.ibm.com/developerworks/cn/linux/kernel/syscall/part1/index.html">http://www.ibm.com/developerworks/cn/linux/kernel/syscall/part1/index.html</a></p>
<p>可以简单的理解为：“系统调用“是在内核之上的一层封装。由内核直接提供接口，“系统调用”需要陷入内核执行（内核态）。其中fdatasync就是一个系统调用，该系统调用可以通知OS立刻将OS Cache中的数据Flush到磁盘文件中。</p>
<p>【附录2】这时候内核会为该该进程打开的文件分配一个文件描述符，并将该文件描述符返回给该进程。在内核的文件表中新建一个文件项，标记文件状态、文件当前偏移、以及I节点（v节点）的位置，内核还会打开该文件的I节点（这里记录文件的操作的函数指针，例如读操作、写操作）。</p>
<p>【附录3】O_RSYNC我的理解是，对于同一个文件描述符可以保证读数据安全。同一个文件描述符包括dup和fcntl函数dup的文件描述符，即共用同一个文件表项。O_RSYNC不是我们今天关注的，暂时忽略</p>
<p>未解问题:</p>
<ol>
<li>O_DIRECT在哪些OS(或者FS)上能够正常工作？</li>
<li>O_SYNC在哪写OS上不能正常工作呢？</li>
<li>内核的read、write是FS级别的还是内核(kernel)级别？</li>
<li>文章<a href="http://rdc.taobao.com/blog/dba/html/296_innodb_flush_method_performance.html">innodb_flush_method带来的性能影响</a>中O_DSYNC、和fdatasync效率差很多，这是为什么？</li>
</ol>
<p>(全文完)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2009/08/innodb_flush_method-file-io/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

