mysql的innodb_flush_method這個參數控制着innodb數據文件及redo log的打開、刷寫模式,對於這個參數,文檔上是這樣描述的:
有三個值:fdatasync(默認),O_DSYNC,O_DIRECT
默認是fdatasync,調用fsync()去刷數據文件與redo log的buffer
爲O_DSYNC時,innodb會使用O_SYNC方式打開和刷寫redo log,使用fsync()刷寫數據文件
爲O_DIRECT時,innodb使用O_DIRECT打開數據文件,使用fsync()刷寫數據文件跟redo logmysql
首先文件的寫操做包括三步:open,write,flush
上面最常提到的fsync(int fd)函數,該函數做用是flush時將與fd文件描述符所指文件有關的buffer刷寫到磁盤,而且flush完元數據信息(好比修改日期、建立日期等)纔算flush成功。
使用O_DSYNC方式打開redo文件表示當write日誌時,數據都write到磁盤,而且元數據也須要更新,才返回成功。
O_DIRECT則表示咱們的write操做是從MySQL innodb buffer裏直接向磁盤上寫。linux
這三種模式寫數據方式具體以下:sql
fdatasync模式:寫數據時,write這一步並不須要真正寫到磁盤纔算完成(可能寫入到操做系統buffer中就會返回完成),真正完成是flush操做,buffer交給操做系統去flush,而且文件的元數據信息也都須要更新到磁盤。
O_DSYNC模式:寫日誌操做是在write這步完成,而數據文件的寫入是在flush這步經過fsync完成
O_DIRECT模式:數據文件的寫入操做是直接從mysql innodb buffer到磁盤的,並不用經過操做系統的緩衝,而真正的完成也是在flush這步,日誌仍是要通過OS緩衝緩存
分別對這個三類模式進行對比測試:服務器
1、測試條件mysql優化
一、1000併發測試單表的增、刪、改、查操做,測試表已經設置索引,基礎數據量是一千五百多萬條(未作分表分庫)併發
二、測試環境:haproxy+2個mycat節點+3臺mysql(第一臺mysql爲主節點,負責寫,另外兩臺負責讀)async
mysql服務器配置:8G內存,8核1.80Ghz CPU函數
三、mysql優化後配置參數:性能
max_connections=2000
innodb_buffer_pool_size=4G
join_buffer_size=1M
sort_buffer_size=1M
thread_cache_size=8
innodb_buffer_pool_instances=8
innodb_page_cleaners=4
innodb_purge_threads=1 #使用單獨的清除線程按期回收無用數據的操做
innodb_max_dirty_pages_pct=90 #innodb主線程刷新緩存池中的數據,使髒數據比例小於90%
wait_timeout=300
###從節點增長以下配置
innodb_doublewrite=off
innodb_page_cleaners=8
innodb_read_io_threads=64
innodb_write_io_threads=64
read_buffer_size=1M
2、測試結果
一、datasync(默認),O_DSYNC這兩種模式的磁盤IO比較高(只截取主節點mysql的監控圖,由於兩個從節點經過主節點同步數據,IO壓力基本一致)
二、O_DIRECT模式的磁盤IO明顯低了好多
這說明O_DIRECT模式是將數據直接從MySQL innodb buffer向磁盤寫入,其寫入磁盤的速度應該是會低於從操做系統buffer往磁盤寫。
三、datasync(默認),O_DSYNC這兩種模式的free內存降低很快(特別是datasync模式)
經過linux中查看,free內存減小,相應的cache就會增多,這與大量將數據寫入到操做系統buffer中有關。
同時對比序號1中的磁盤IO變化狀況圖就發現,free內存越少,IO就越大,這與頁交換頻繁相符合(頁換出越大,磁盤寫入的壓力越大):
四、O_DIRECT模式的free內存降低比較慢
五、對比其餘測試結果以下:
從對比數據能夠看出,O_DSYNC對CPU的壓力最大,datasync次之,O_DIRECT最小;總體SQL語句處理性能和響應時間看,O_DSYNC都較差;O_DIRECT在SQL吞吐能力上較好(僅次於datasync模式),但響應時間倒是最長的。
3、初步結論
終上結果作出分析以下:
(1)在類unix操做系統中,文件的打開方式爲O_DIRECT會最小化緩衝對io的影響,該文件的io是直接在用戶空間的buffer上操做的,而且io操做是同步的,所以不論是read()系統調用仍是write()系統調用,數據都保證是從磁盤上讀取的;因此IO方面壓力最小,對於CPU處理壓力上也最小,對物理內存的佔用也最小;可是因爲沒有操做系統緩衝的做用,對於數據寫入磁盤的速度會下降明顯(表現爲寫入響應時間的拉長),但不會明顯形成總體SQL請求量的下降(這有賴於足夠大的innodb_buffer_pool_size)。
(2)O_DSYNC方式表示以同步io的方式打開文件,任何寫操做都將阻塞到數據寫入物理磁盤後才返回。這就形成CPU等待加長,SQL請求吞吐能力下降,insert時間拉長。
(3)fsync(int filedes)函數只對由文件描述符filedes指定的單一文件起做用,而且等待寫磁盤操做結束,而後返回。fdatasync(int filedes)函數相似於fsync,但它隻影響文件的數據部分。而除數據外,fsync還會同步更新文件的元信息到磁盤。
默認datasync模式,總體表現較好,由於充分利用了操做系統buffer和innodb_buffer_pool的處理性能,但帶來的負面效果是free內存下降過快,最後致使頁交換頻繁,磁盤IO壓力大,這會嚴重影響大併發量數據寫入的穩定性。也就是說擁有了高性能,但不會有高穩定性(特別是mycat集羣,在大量數據寫入和各節點mysql數據同步壓力下,IO是很大的)。爲了解決這個問題,能夠有個折中的辦法,定時的對操做系統進行echo 3 >/proc/sys/vm/drop_caches,清理一下OS緩存,能夠及時回收一部份內存(回收順間對性能會有所影響)。
O_DIRECT模式網上一些評論認爲是性能最好的,但本次測試的結果來看,性能並非很高,可是穩定性確實比較高,在大併發量讀寫操做中,可以較長時間運行,只是在第一次啓動系統後測試,該模式一開始的響應時間確實比較長,到後面才恢復到較低水平(分析的緣由是由於有兩個mysql節點變成寫模式了,可能重啓mysql出現讀寫狀態變化,在作這個測試時因爲開發人員還配了Galera,兩節點同時寫入是基於row級的,因此開始很容易引發鎖,響應時間就變得很慢),以下所示:
總結:對於mycat讀寫分離中,寫數據壓力小,讀數據壓力大的狀況下,而且內存夠大,innodb_buffer_pool_size配置夠大的狀況下,其實三種模式應該都行,讀數據的性能基本是依賴於緩存,若是從穩定性和內存使用狀況來考慮,用O_DIRECT模式會更好些,並經過優化查詢以彌補響應時間不夠快的問題。對於讀寫壓力都很大或只是寫的壓力大的狀況下,建議用datasync模式,並配上按期清理系統緩存的機制。若是咱們充分應用了mycat的分表分庫和讀寫分離機制,那麼對於總體系統的性能和穩定性都有幫助(由於大庫和大表,都會嚴重下降數據的寫入和讀出性能,這樣的話光是靠innodb_flush_method的模式配置也是治標不治本)。
至於,生產環境如何設置必定要以壓測結果爲準,以實際效果爲準,不能盲目信任經驗值。
跟你們推薦一個學習資料分享羣:747981058,裏面大牛已經爲咱們整理好了許多的學習資料,有自動化,接口,性能等等的學習資料!人生是一個逆水行舟的過程,不進則退,我們一塊兒加油吧!