MySQL/InnoDB和Group Commit

G8bao7發表於2015-05-27
from:


https://www.percona.com/blog/2011/07/13/testing-the-group-commit-fix/

http://blog.itpub.net/22664653/viewspace-1063134/

1. 什麼是Group Commit

簡單的,InnoDB在每次提交事務時,為了保證資料已經持久化到磁碟(Durable),需要呼叫一次fsync(或者是fdatasync、或者使用O_DIRECT選項等)來告知檔案系統將可能在快取中的資料重新整理到磁碟(更多關於)。而fsync操作本身是非常“昂貴”的(關於“昂貴”:消耗較多的IO資源,響應較慢):傳統硬碟(10K轉/分鐘)大約每秒支撐150個fsync操作,SSD(Intel X25-M)大約每秒支撐1200個fsync操作。所以,如果每次事務提交都單獨做fsync操作,那麼這裡將是系統TPS的一個瓶頸。所以就有了Group Commit的概念。

當多個事務併發時,我們讓多個都在等待fsync的事務一起合併為僅呼叫一次fsync操作。這樣的一個簡單的最佳化將大大提高系統的吞吐量,Yoshinori Matsunobu的實驗表明,這將帶來五到六倍的效能提升。

MySQL/InnoDB在做事務的時候使用的日誌先行()的方式保證事務的快速和持久,所以每次事務完成都要求日誌必須持久化到磁碟
    為了保證資料已經持久化到磁碟(Durable),需要呼叫一次fsync(或者是fdatasync、或者使用O_DIRECT選項等)來告知檔案系統將可能在快取中的資料重新整理到磁碟(更多關於)。而fsync操作本身是非常“昂貴”的(關於“昂貴”:消耗較多的IO資源,響應較慢):傳統硬碟(10K轉/分鐘)大約每秒支撐150個fsync操作,SSD(Intel X25-M)大約每秒支撐1200個fsync操作。所以,如果每次事務提交都單獨做fsync操作,那麼這裡將是系統TPS的一個瓶頸。
     
在Linux上對應的操作就是“”,write速度是很快的,一般對應的寫Page Cache,而fsync則要求檔案系統把對應檔案的哦Page Cache必須持久化到磁碟上,而對於傳統磁碟一次寫操作大約需要1~3ms(不說BBU),這意味著對於傳統磁碟1秒鐘最多最多做333~1000個事務,這是不理想的,對硬體的利用率(吞吐量)也是非常低。

所以,這裡就有了Group操作的概念,即當好幾個執行緒都要fsync同一個日誌檔案時,我們將這些fsync合併到一次來做。簡單舉例:我們讓系統每2ms做一次fsync,這樣如果這2ms內有100個執行緒都需要做fsync,那就賺到了,原本100個fsync都獨立來做那耗時會非常多的。

2. MySQL/InnoDB與Group Commit

MySQL5.0開始,InnoDB就不再支援Group Commit了。在2005年,Peter Zaitsev就將此作為一個提交,直到2009年在InnoDB Plugin1.0.4才將此問題修復。

2.1 為什麼5.0之後MySQL/InnoDB無法支援Group Commit

究其更本原因發現,5.0之後MySQL開始支援“分散式事務和兩階段提交協議”(distributed transactions and Two Phase Commit /2PC),在程式碼實現時為了保證Binlog中的事務順序和InnoDB Log(Transaction Log或者叫redo log)事務順序一致,被動放棄了Group Commit。如果Binlog順序不一致,那麼備庫就無法確保和主庫有一致的資料。

InnoDB本身的程式碼實現是可以支援Group Commit的,我們來看下面的程式碼:

如果你設定了binlog_sync=1,則又多了一次fsync操作(參考MYSQL_BIN_LOG::flush_and_sync),這次操作在innobase_xa_prepare和innodb_commit之間:

binlog_prepare (do nothing)
innodb_prepare(innobase_xa_prepare)
...
binlog_commit
innobase_commit

innobase_xa_prepare()
write() and fsync() binary log
innobase_commit()

在innobase_xa_prepare函式中需要獲取排他鎖,直到上面的innodb_commit結束鎖才釋放,所以上面的binlog write and fsync也就無法Group操作了(當binlog_sync=1時)InnoDB就無法做Group_commit了,如果prepare_commit_mutex提前釋放了,則可能導致InnoDB內部的事務順序和Binlog內部事務的順序不一致(: [12254|12408|12553|12810].html)。

    當sync_binlog=1 和innodb-flush-log-at-trx-commit=1 同時啟用時,在寫密集的環境中效能的急劇下降


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26250550/viewspace-1674192/,如需轉載,請註明出處,否則將追究法律責任。

相關文章