MySQL組提交(group commit)

MySQL組提交(group commit) 

 

640?wx_fmt=gif

 

 

前提:html

  • 如下討論的前提 是設置MySQL的crash safe相關參數爲雙1:sql

sync_binlog=1數據庫

innodb_flush_log_at_trx_commit=1安全

 

背景說明:post

  • WAL機制 (Write Ahead Log)定義:性能

    WAL指的是對數據文件進行修改前,必須將修改先記錄日誌。MySQL爲了保證ACID中的一致性和持久性,使用了WAL。.net

  • Redo log的做用:日誌

    Redo log就是一種WAL的應用。當數據庫突然掉電,再從新啓動時,MySQL能夠經過Redo log還原數據。也就是說,每次事務提交時,不用同步刷新磁盤數據文件,只須要同步刷新Redo log就足夠了。相比寫數據文件時的隨機IO,寫Redo log時的順序IO可以提升事務提交速度。xml

  • 組提交的做用:htm

    • 在沒有開啓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 組提交三個階段的流程:

640?wx_fmt=jpeg

 

在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被修復。

 

轉載:https://blog.csdn.net/n88Lpo/article/details/81187372

相關文章
相關標籤/搜索