MySQL複製(三) - binlog組提交
通過sync_binlog=1控制事件持久化到磁碟,每次事務提交時進行fsync操作,將消耗大量的磁碟IOPS,如何最大化的提高效能,降低fsync對事務高併發的影響呢?
一. 二階段提交
binlog是MySQL服務層產生的日誌,每個執行緒有獨立的快取,在事務提交時才寫入磁碟(fsync行為依賴sync_binlog設定),無法進行回滾,是邏輯的日誌,記錄行的改變或SQL語句。
redo日誌(WAL)是InnoDB儲存引擎產生的日誌,在事務的執行過程中一直會產生,所有執行緒共享記憶體快取(innodb_log_buffer_size),事務提交時會進行刷盤操作(fsync行為依賴innodb_flush_log_at_trx_commit設定),同時也會將沒提交的事務日誌順帶寫入磁碟,寫了redo的事務也能回滾。
binlog和redo是由不同的子系統產生的,兩個子系統怎麼協調,以保證binlog和redo的資料一致性呢?在分散式系統中,MySQL通過分散式事務(innodb_support_xa=1,8.0預設使用)來解決兩者的一致性問題,在事務提交時,redo先寫prepare 日誌,並做刷盤,然後寫binlog,並刷盤,寫成功後,再進行寫redo commit日誌。
二階段提交流程圖:
當prepare日誌寫成功,在寫binlog日誌時MySQL宕機,binlog沒寫成功(a位置),恢復時將回滾該事務,因binlog沒寫成功,如果事務進行提交的話,將會造成redo和binlog的不一致,引起主從資料不一致。
當prepare日誌和binlog都寫成功,如果發生宕機(b位置),在恢復時會通過Xid去binlog日誌查詢是否有對應事務的完整日誌,如binlog完整,儘管沒有redo commit日誌,也要進行事務提交,因binlog不能回滾,如果redo回滾,將會造成主從不一致,如沒有完整的binlog日誌將進行事務回滾。
二. binlog組提交
在MySQL 5.6之前,同時為了保障物理熱備份工具,其備份資料的一致性,二階段提交期間有prepare_commit_mutex鎖,造成多個事務的提交是序列的,同時redo group commit也失效,引起效能問題。
為了解決該效能問題,5.6通過BLGC(Binary Log Group Commit)的機制進行了優化,將binlog的寫分為三個階段:flush,sync,commit,每個階段由leader和follower組成,由leader控制follower的行為(follower不能成為leader),在commit階段由leader按順序呼叫儲存引擎進行事務的提交,同時也去掉prepare_commit_mutex鎖,提高了效能。
為了提高一次fsync操作更多的事務,提供了一些引數:
-
binlog_max_flush_queue_time(5.7.9棄用),控制事務在flush佇列中等待的時間;
-
binlog_group_commit_sync_delay,等待多少微秒後才進行fsync;
-
binlog_group_commit_sync_no_delay_count,達到等待的事務數量後呼叫fsync操作;
以上控制組提交的引數需要結合業務情況進行配置,當多執行緒(併發量)寫時,效果更好。
全文完。
來源: