深入理解Fsync


1 介紹

數據庫系統從誕生那天開始,就面對一個很棘手的問題,fsync的性能問題。組提交(group commit)就是為了解決fsync的問題。最近,遇到一個業務反映MySQL創建分區表很慢,仔細分析了一下,發現InnoDB在創建表的時候有很多fsync——每個文件會有4個fsync的調用。當然,並不每個fsync的開銷都很大。

 

clip_image002

這里引出幾個問題:

(1)問題1為什么fsync開銷相對都比較大?它到底做了什么?

(2)問題2:細心的人可以發現,第一次open數據文件后,第二次fsync的時間遠遠小於第1次調用fsync的時間,為什么?

clip_image002[5]

(3)問題3能否優化fsync?

來着這些疑問,一起來了解一下fsync。

2 原因分析

我們先通過一個測試程序來學習一下fsync在塊層的基本流程。

2.1 測試程序1

Write page 0

Sleep 5

Fsync

用blktrace跟蹤結果如下:

clip_image004

上半部紅色框內為pwrite在塊層的流程,下半部黃色框內為fsync在塊層流程,中間剛好相差5秒。

4722712為測試文件的第1個block對應的扇區號,590339(block號) * 8=4722712(扇區號)。

clip_image006

無論是pwrite,還是fsync,主要的開銷都發生IO請求提交給驅動和IO完成之間,也就是說開自設備驅動。差不多占了整個系統調用的1/2的開銷。

另外,可以看到調用fsync時,發生了3次塊層IO,起始扇區分別是19240、19248和19256,物理上3個連續的塊。實際上這3個塊為內核線程kjournald寫的日志,分別描述塊(2405)、數據塊(2406)和提交塊(2407)。為了驗證,不妨看一下這三個塊的實際數據。

塊2405:

clip_image008

#define JFS_MAGIC_NUMBER 0xc03b3998U

#define JFS_DESCRIPTOR_BLOCK 1

#define JFS_COMMIT_BLOCK 2

開始的4個字節為JFS_MAGIC_NUMBER,然后是block type:JFS_DESCRIPTOR_BLOCK。

塊2407:

clip_image010

的確是提交塊。

2.2 fsync的實現

既然fsync的開銷很大,就來看看代碼吧。

函數ext3_sync_file:

clip_image012

函數log_start_commit負責喚醒kjounald內核線程,log_wait_commit等待jbd事務提交完成。

clip_image014

從代碼來看,fsync的主要開銷在於調用log_wait_commit后的等待。也就是說fsync要等待kjournald把事務提交完成,才會返回。

到這里,我們已經知道了fsync開銷的主要來源:(1)硬件驅動層的開銷;(2)ext3寫日志。

另外,當log_start_commit返回0時,fsync就不會等待事務提交完成。到這里已經基本可以確認第2次fsync的開銷為什么那么小了——沒有wait事務提交。

下面驗證這一想法。為了方便調試,打開了內核jbd debug日志。

2.3 測試程序2

Write page 0

Fsync

Write page 0

Fsync

Write page 1

Fsync

Write page 2

Fsync

clip_image016

clip_image018

從第2個紅框的日志來看,第2次fsync時,的確是沒有wait的,所以開銷這么小,而其它3次fsync都調用了log_wait_commit函數。

問題4:第2次fsync為什么不會調用log_wait_commit

因為掛載文件系統的時候,data=writeback,即寫數據本身不會寫jbd日志。第2次pwrite沒有引起文件擴展,只會修改ext3 inode的i_mtime,而i_mtime只精確到second,也就是說第2次pwrite不會引起inode信息改變,所以,不會生成jbd日志,也就不需要等待事務提交完成。

clip_image020

下面驗證一下該想法。

2.4 測試程序3

Write page 0

Fsync

Sleep 1 second

Write page 0

Fsync

Write page 1

Fsync

Write page 2

Fsync

在第2次pwrite之前,sleep 1秒鍾,保證ext3 inode的i_mtime修改。

clip_image022

想法被證實了,第2次fsync的時間回到正常水平。

clip_image024

可以看到,第2次fsync調用提交了新的事務,並調用了log_wait_commit等待事務完成。

3 優化

如何優化fsync?是個難題。

(1)系統減少對fsync的調用。

(2)ext3日志放在更快的存儲介質,參考http://insights.oetiker.ch/linux/external-journal-on-ssd/


作者:YY哥
出處:http://www.cnblogs.com/hustcat/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM