mysql5 7組提交 mysql組提交

2021-10-18 21:42:44 字數 2770 閱讀 4014

當mysql開啟binlog日誌時,會存在乙個內部xa的問題:事務在儲存引擎層redo log的寫入和binlog的寫入一致性問題。

mysql通過兩階段提交很好的解決了redo log和binlog一致性問題:

第一階段:innodb prepare, 持有prepare_commit_mutex,redo log持久化到磁碟(flush/sync redolog),並將回滾段設定為prepare狀態。

第二階段:分為兩步。

a. flush/sync binlog

b. commit(寫入commit標記,釋放prepare_commit_mutex,並釋放回滾段)

事務的崩潰恢復過程如下:

1. 事務恢復時,掃瞄最後乙個binlog,提取出其中的xid

2. xid也會寫到redo中,重做檢查點後的所有事務,包括未提交的事務和已回滾的事務,讀取事務的undo段資訊,蒐集處於prepare階段的事務鍊錶,將redo中prepared狀態的xid與binlog中的xid做比較,如果在binlog中存在,則提交;否則回滾。

為什麼只掃瞄最後乙個binlog?

因為binlog rotate的binlog檔案中對應的事務一定是已經提交的

group commit:

上面的整個過程,通過持有 prepare_commit_mutex來保證redolog的寫入和binlog的寫入完全一致,會導致group commit無法生效。

在mysql56中,同時支援了redolog 和 binlog的組提交,其提交流程如下:

第一階段: innodb prepare(redo group commit)

在innodb中,每條redolog都有自己的lsn,這是乙個單調遞增的值。每個事務的更新操作都會包含一條或者多條redo log, 各個事務在將redo log寫入 log_sys_buffer(通過log_sys mutex保護)時,都會獲取當前事務最大的lsn。那麼假設三個事務 tx1, tx2, tx3的最大lsn分別為 lsn1 < lsn2 < lsn3時,他們同時進行提交,如果tx3獲取到了 log_mutex, 那麼他會將小於lsn3之前的redo log一起落盤,這樣 tx1, tx2不用再次請求磁碟io。同時,如果存在tx0的lsn0 < lsn3,lsn0也會落盤,即使tx0還沒有提交。

1. 獲取 log mutex

2. 如果 flushed_to_disk_lsn >= lsn, 表示日誌已經被刷盤,跳轉 5

3. 如果 current_flush_lsn >= lsn, 表示日誌正在刷盤中,跳轉 5 後進入等待狀態

4. 將小於 lsn 的日誌刷盤 (flush and sync)

5. 退出 log_mutex

第二階段: binlog group commit的基本思想是引入佇列機制,保證 innodb commit 的順序與 binlog落盤的順序一致,並將事務分組,組內的 binlog刷盤動作交給乙個事務進行,實現組提交的目的。佇列中的第乙個事務稱為 leader, 其他事務稱為 follower。所有的事情交給 leader 去做。: flush stage, sync stage, commit stage

flush stage:

將每個事務的 binlog 寫入記憶體

1. 持有 lock_log mutex [leader持有,follwer等待]

2. 獲取佇列中的一組 binlog(佇列中的所有事務)

3. 將 binlog buffer 到 i/o cache

4. 通知 dump執行緒 dump binlog [sync_binlog != 1]

sync stage:

將記憶體中的二進位制日誌重新整理到磁碟, 若佇列中有多個事務,那麼僅一次 fsync 操作就完成了二進位制日誌的寫入,這就是 blgc。

1. 釋放 lock_log mutex, 持有 lock_sync mutex[leader持有,follower等待]

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

3. 通知 dump執行緒 dump binlog [sync_binlog = 1]

commit stage:

leader根據順序呼叫儲存引擎層的提交

1. 釋放 lock_sync mutex, 持有 lock_commit mutex[ leader持有,follower等待]

2. 遍歷佇列中的事務,逐一進行 innodb commit.

3. 釋放 lock_commit mutex

4. 喚醒佇列中等待的執行緒。

redo group commit優化

每個事務提交時,都會觸發一次redo flush/sync動作,由於磁碟讀寫比較慢,因此很影響系統的吞吐量。

mysql57中,做了針對redo group commit的優化。將 redo log的write/sync延遲到了binlog group commit的 flush stage之後,sync binlog之前。

通過延遲寫redo log的方式,顯式的為redo log做了一次組寫入,並減少了(redo log) log_sys->mutex的競爭。

第一階段:innodb prepare

1. 記錄當前的lsn到thd中

第二階段:binlog group commit

1. 進入binlog group commit的flush階段;同時,leader搜尋佇列,算出thd中最大的lsn

2. 將innodb的redo log flush/sync到指定lsn

3. sync binlog

4. commit

參考

mysql5 7學習 mysql 5 7 學習

mysql uroot proot mysql5.7 mysql.user表沒有password欄位改 authentication string 一.建立使用者 命令 create user username host identified by password 例子 create user d...

mysql5 7如何開啟 mysql57怎麼開啟

開啟mysql57的方法 首先開啟winodws執行視窗 然後在開啟編輯框中輸入cmd命令 最後在終端介面中輸入 mysql hlocalhost uroot p123 即可顯示開啟mysql資料庫。windows下用命令列啟動mysql5.7 win菜單鍵即是在鍵盤左下角 ctrl控制 鍵與 al...

mysql5 7如何開啟 mysql57怎麼開啟

開啟mysql57的方法 首先開啟winodws執行視窗 然後在開啟編輯框中輸入cmd命令 最後在終端介面中輸入 mysql hlocalhost uroot p123 即可顯示開啟mysql資料庫。windows下用命令列啟動mysql5.7 win菜單鍵即是在鍵盤左下角 ctrl控制 鍵與 al...