1. 程式人生 > >針對innodb_flush_method引數的理解和對比測試(mycat+mysql)

針對innodb_flush_method引數的理解和對比測試(mycat+mysql)

    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 log

首先檔案的寫操作包括三步:open,write,flush
上面最常提到的fsync(int fd)函式,該函式作用是flush時將與fd檔案描述符所指檔案有關的buffer刷寫到磁碟,並且flush完元資料資訊(比如修改日期、建立日期等)才算flush成功。
使用O_DSYNC方式開啟redo檔案表示當write日誌時,資料都write到磁碟,並且元資料也需要更新,才返回成功。
O_DIRECT則表示我們的write操作是從MySQL innodb buffer裡直接向磁碟上寫。

這三種模式寫資料方式具體如下:

fdatasync模式:寫資料時,write這一步並不需要真正寫到磁碟才算完成(可能寫入到作業系統buffer中就會返回完成),真正完成是flush操作,buffer交給作業系統去flush,並且檔案的元資料資訊也都需要更新到磁碟。
O_DSYNC模式:寫日誌操作是在write這步完成,而資料檔案的寫入是在flush這步通過fsync完成
O_DIRECT模式:資料檔案的寫入操作是直接從mysql innodb buffer到磁碟的,並不用通過作業系統的緩衝,而真正的完成也是在flush這步,日誌還是要經過OS緩衝

分別對這個三類模式進行對比測試:

一、測試條件

1、1000併發測試單表的增、刪、改、查操作,測試表已經設定索引,基礎資料量是一千五百多萬條(未做分表分庫)

2、測試環境:haproxy+2個mycat節點+3臺mysql(第一臺mysql為主節點,負責寫,另外兩臺負責讀)

mysql伺服器配置:8G記憶體,8核1.80Ghz CPU

3、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

二、測試結果

1、datasync(預設),O_DSYNC這兩種模式的磁碟IO比較高(只擷取主節點mysql的監控圖,因為兩個從節點通過主節點同步資料,IO壓力基本一致)

2、O_DIRECT模式的磁碟IO明顯低了好多

這說明O_DIRECT模式是將資料直接從MySQL innodb buffer向磁碟寫入,其寫入磁碟的速度應該是會低於從作業系統buffer往磁碟寫。

3、datasync(預設),O_DSYNC這兩種模式的free記憶體下降很快(特別是datasync模式)

通過linux中檢視,free記憶體減少,相應的cache就會增多,這與大量將資料寫入到作業系統buffer中有關。

同時對比序號1中的磁碟IO變化情況圖就發現,free記憶體越少,IO就越大,這與頁交換頻繁相符合(頁換出越大,磁碟寫入的壓力越大):

4、O_DIRECT模式的free記憶體下降比較慢

5、對比其他測試結果如下:

從對比資料可以看出,O_DSYNC對CPU的壓力最大,datasync次之,O_DIRECT最小;整體SQL語句處理效能和響應時間看,O_DSYNC都較差;O_DIRECT在SQL吞吐能力上較好(僅次於datasync模式),但響應時間卻是最長的。

三、初步結論

終上結果做出分析如下:

(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,裡面大牛已經為我們整理好了許多的學習資料,有自動化,介面,效能等等的學習資料!人生是一個逆水行舟的過程,不進則退,咱們一起加油吧!