MySQL組提交group commit詳解
引 言
前提:
- 以下討論的前提 是設置MySQL的crash safe相關參數為雙1:
sync_binlog=1
innodb_flush_log_at_trx_commit=1
背景說明:
- WAL機制 (Write Ahead Log)定義: WAL指的是對數據文件進行修改前,必須將修改先記錄日志。MySQL為瞭保證ACID中的一致性和持久性,使用瞭WAL。
- Redo log的作用: Redo log就是一種WAL的應用。當數據庫忽然掉電,再重新啟動時,MySQL可以通過Redo log還原數據。也就是說,每次事務提交時,不用同步刷新磁盤數據文件,隻需要同步刷新Redo log就足夠瞭。相比寫數據文件時的隨機IO,寫Redo log時的順序IO能夠提高事務提交速度。
- 組提交的作用:
- 在沒有開啟binlog時
Redo log的刷盤操作將會是最終影響MySQL TPS的瓶頸所在。為瞭緩解這一問題,MySQL使用瞭組提交,將多個刷盤操作合並成一個,如果說10個事務依次排隊刷盤的時間成本是10,那麼將這10個事務一次性一起刷盤的時間成本則近似於1。
- 當開啟binlog時
為瞭保證Redo log和binlog的數據一致性,MySQL使用瞭二階段提交,由binlog作為事務的協調者。而 引入二階段提交 使得binlog又成為瞭性能瓶頸,先前的Redo log 組提交 也成瞭擺設。為瞭再次緩解這一問題,MySQL增加瞭binlog的組提交,目的同樣是將binlog的多個刷盤操作合並成一個,結合Redo log本身已經實現的 組提交,分為三個階段(Flush 階段、Sync 階段、Commit 階段)完成binlog 組提交,最大化每次刷盤的收益,弱化磁盤瓶頸,提高性能。
圖解:
下圖我們假借“渡口運輸”的例子來看看binlog 組提交三個階段的流程:
在MySQL中每個階段都有一個隊列,每個隊列都有一把鎖保護,第一個進入隊列的事務會成為leader,leader領導所在隊列的所有事務,全權負責整隊的操作,完成後通知隊內其他事務操作結束。
Flush 階段 (圖中第一個渡口)
- 首先獲取隊列中的事務組
- 將Redo log中prepare階段的數據刷盤(圖中Flush Redo log)
- 將binlog數據寫入文件,當然此時隻是寫入文件系統的緩沖,並不能保證數據庫崩潰時binlog不丟失 (圖中Write binlog)
- Flush階段隊列的作用是提供瞭Redo log的組提交
- 如果在這一步完成後數據庫崩潰,由於協調者binlog中不保證有該組事務的記錄,所以MySQL可能會在重啟後回滾該組事務
Sync 階段 (圖中第二個渡口)
- 這裡為瞭增加一組事務中的事務數量,提高刷盤收益,MySQL使用兩個參數控制獲取隊列事務組的時機:
binlog_group_commit_sync_delay=N:在等待N μs後,開始事務刷盤(圖中Sync binlog)
binlog_group_commit_sync_no_delay_count=N:如果隊列中的事務數達到N個,就忽視binlog_group_commit_sync_delay的設置,直接開始刷盤(圖中Sync binlog)
- Sync階段隊列的作用是支持binlog的組提交
- 如果在這一步完成後數據庫崩潰,由於協調者binlog中已經有瞭事務記錄,MySQL會在重啟後通過Flush 階段中Redo log刷盤的數據繼續進行事務的提交
Commit 階段 (圖中第三個渡口)
- 首先獲取隊列中的事務組
- 依次將Redo log中已經prepare的事務在引擎層提交(圖中InnoDB Commit)
- Commit階段不用刷盤,如上所述,Flush階段中的Redo log刷盤已經足夠保證數據庫崩潰時的數據安全瞭
- Commit階段隊列的作用是承接Sync階段的事務,完成最後的引擎提交,使得Sync可以盡早的處理下一組事務,最大化組提交的效率
缺陷分析:
本文最後要討論的bug(可通過閱讀原文查看)就是來源於Sync 階段中的那個binlog參數binlog_group_commit_sync_delay,在MySQL 5.7.19中,如果該參數不為10的倍數,則會導致事務在Sync 階段等待極大的時間,表現出來的現象就是執行的sql長時間無法返回。該bug已在MySQL 5.7.24和8.0.13被修復。
到此這篇關於MySQL組提交(group commit)的文章就介紹到這瞭,更多相關MySQL組提交內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 一條SQL更新語句的執行過程解析
- 一文搞懂MySQL持久化和回滾的原理
- MySQL 主從同步,事務回滾的實現原理
- Mysql中undo、redo與binlog的區別淺析
- MySQL日志專項之redo log和undo log介紹