MYSQL組提交

來源:互聯網
上載者:User

標籤:

     組提交(group commit)是MYSQL處理日誌的一種最佳化方式,主要為瞭解決寫日誌時頻繁刷磁碟的問題。組提交伴隨著MYSQL的發展不斷最佳化,從最初只支援redo log 組提交,到目前5.6官方版本同時支援redo log 和binlog組提交。組提交的實現大大提高了mysql的交易處理效能,下文將以innodb 儲存引擎為例,詳細介紹組提交在各個階段的實現原理。

redo log的組提交

     WAL(Write-Ahead-Logging)是實現事務持久性的一個常用技術,基本原理是在提交事務時,為了避免磁碟頁面的隨機寫,只需要保證事務的redo log寫入磁碟即可,這樣可以通過redo log的順序寫代替頁面的隨機寫,並且可以保證事務的持久性,提高了資料庫系統的效能。雖然WAL使用順序寫替代了隨機寫,但是,每次事務提交,仍然需要有一次日誌刷盤動作,受限於磁碟IO,這個操作仍然是事務並發的瓶頸。

      組提交思想是,將多個事務redo log的刷盤動作合并,減少磁碟順序寫。Innodb的日誌系統裡面,每條redo log都有一個LSN(Log Sequence Number),LSN是單調遞增的。每個事務執行更新操作都會包含一條或多條redo log,各個事務將日誌拷貝到log_sys_buffer時(log_sys_buffer 通過log_mutex

保護),都會擷取當前最大的LSN,因此可以保證不同事務的LSN不會重複。那麼假設三個事務Trx1,Trx2和Trx3的日誌的最大LSN分別為LSN1,LSN2,LSN3(LSN1<LSN2<LSN3),它們同時進行提交,那麼如果Trx3日誌先擷取到log_mutex進行落盤,它就可以順便把[LSN1---LSN3]這段日誌也刷了,這樣Trx1和Trx2就不用再次請求磁碟IO。組提交的基本流程如下:

  1. 擷取 log_mutex
  2. 若flushed_to_disk_lsn>=lsn,表示日誌已經被刷盤,跳轉5
  3. 若 current_flush_lsn>=lsn,表示日誌正在刷盤中,跳轉5後進入等待狀態
  4. 將小於LSN的日誌刷盤(flush and sync)
  5. 退出log_mutex

備忘:lsn表示事務的lsn,flushed_to_disk_lsn和current_flush_lsn分別表示已刷盤的LSN和正在刷盤的LSN。 

兩階段交易認可

     在單機情況下,redo log組提交很好地解決了日誌落盤問題,那麼開啟binlog後,binlog能否和redo log一樣也開啟組提交?首先開啟binlog後,我們要解決的一個問題是,如何保證binlog和redo log的一致性。因為binlog是Master-Slave的橋樑,如果順序不一致,意味著Master-Slave可能不一致。MYSQL通過兩階段交易認可很好地解決了這一問題。Prepare階段,innodb刷redo log,並將復原段設定為Prepared狀態,binlog不作任何操作;commit階段,innodb釋放鎖,釋放復原段,設定提交狀態,binlog刷binlog日誌。出現異常,需要故障恢複時,若發現事務處於Prepare階段,並且binlog存在則提交,否則復原。通過兩階段交易認可,保證了redo log和binlog在任何情況下的一致性。

binlog的組提交

      回到上節的問題,開啟binlog後,如何在保證redo log-binlog一致的基礎上,實現組提交。因為這個問題,5.6以前,mysql在開啟binlog的情況下,無法實現組提交,通過一個臭名昭著的prepare_commit_mutex,將redo log和binlog刷盤序列化,序列化的目的也僅僅是為了保證redo log-Binlog一致,但這種實現方式犧牲了效能。這個情況顯然是不能容忍的,因此各個mysql分支,mariadb,facebook,perconal等相繼出了補丁改進這一問題,mysql官方版本5.6也終於解決了這一問題。由於各個分支版本解決方案類似,我主要通過分析5.6的實現來說明實現方法。

     binlog組提交的基本思想是,引入隊列機制保證innodb commit順序與binlog落盤順序一致,並將事務分組,組內的binlog刷盤動作交給一個事務進行,實現組提交目的。binlog提交將提交分為了3個階段,FLUSH階段,SYNC階段和COMMIT階段。每個階段都有一個隊列,每個隊列有一個mutex保護,約定進入隊列第一個線程為leader,其他線程為follower,所有事情交由leader去做,leader做完所有動作後,通知follower刷盤結束。binlog組提交基本流程如下:

FLUSH 階段

1)      持有Lock_log mutex [leader持有,follower等待]

2)      擷取隊列中的一組binlog(隊列中的所有事務)

3)      將binlog buffer到I/O cache

4)      通知dump線程dump binlog

SYNC階段

1)      釋放Lock_log mutex,持有Lock_sync mutex[leader持有,follower等待]

2)      將一組binlog 落盤(sync動作,最耗時,假設sync_binlog為1)

COMMIT階段

1)      釋放Lock_sync mutex,持有Lock_commit mutex[leader持有,follower等待]

2)      遍曆隊列中的事務,逐一進行innodb commit

3)      釋放Lock_commit mutex

4)      喚醒隊列中等待的線程

說明:由於有多個隊列,每個隊列各自有mutex保護,隊列之間是順序的,約定進入隊列的一個線程為leader,因此FLUSH階段的leader可能是SYNC階段的follower,但是follower永遠是follower。

      通過上文分析,我們知道MYSQL目前的組提交方式解決了一致性和效能的問題。通過二階段提交解決一致性,通過redo log和binlog的組提交解決磁碟IO的效能。下面我整理了Prepare階段和Commit階段的架構圖供各位參考。

 

參考文檔

http://mysqlmusings.blogspot.com/2012/06/binary-log-group-commit-in-mysql-56.html

http://www.lupaworld.com/portal.php?mod=view&aid=250169&page=all

http://www.oschina.net/question/12_89981

http://kristiannielsen.livejournal.com/12254.html

http://blog.chinaunix.net/uid-26896862-id-3432594.html

MYSQL組提交

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.