MySQL 5.7並行複製

賀子_DBA時代發表於2021-04-12
關於mysql 5.7的並行複製策略,mysql 5.7.22開始支援的 基於writeset的並行複製策略
mysql多執行緒複製,需要遵循兩個基本原則:1.不能造成更新覆蓋,這就要求更新同一行的兩個事務,必須被分發到同一個worker中,2.同一個事務不能被拆開,必須放到同一worker中!
一:5.7.22之前的COMMIT_ORDER並行複製方式,藉助mysql的組提交,根據mysql兩階段提交,可以知道能達到redo  log  prepare階段以及commit階段的事務,就表示事務已經透過鎖衝突的檢驗了!換句話說只要不是更新同一行,就可以並行複製!
MySQL 5.7 commit_order的並行複製策略的思想是:
1). 同時處於 prepare 狀態的事務,在備庫執行時是可以並行的;
2). 處於 prepare 狀態的事務,與處於 commit 狀態的事務之間,在備庫執行時也是可以並行的,
針對commit_order的方式的並行複製策略,可以透過修改如下兩個引數來影響併發的事務個數!
1) binlog_group_commit_sync_delay 引數,表示延遲多少微秒後才呼叫 fsync;
2)binlog_group_commit_sync_no_delay_count 引數,表示累積多少次以後才呼叫fsync。這兩個引數是用於故意拉長 binlog 從 write 到 fsync的時間,以此減少 binlog 的寫盤次數。在 MySQL 5.7 的並行複製策略裡(COMMIT_ORDER方式),它們可以用來製造更多的“同時處於 prepare 階段的事務”。這樣就增加了備庫複製的並行度。
二:mysql 5.7.22開始的基於writeset的並行複製策略中
2.1即便是主庫是單執行緒執行的,那麼從庫也可能是並行的,只要沒有衝突!之前COMMIT_ORDER方式是判斷同時處於redo prepare或者commit的事務可以一同提交,這些事務的last committed一樣。現在基於writeset的併發複製,計算last committed的方式發生變化,會依照事務的 write_set 中的HASH值與已提交的事務的 write_set 進行比對,如果沒有衝突,則當前事務與最後一個已提交的事務共享相同的 last_commited, 否則將從全域性已提交的 write_set 中刪除那個衝突的事務以及之前提交的所有write_set,並退化到 COMMIT_ORDER 計算last_committed 。 每次計算完事務的 last_committed 值以後,檢測當前全域性已提交事務的 write_set 是否已經超過了 binlog_transaction_dependency_history_size 設定的值,如果超過,則清空已提交事務的全域性 write_set,從新開始記錄,清空之後意味著下一個也就是第一個事務肯定是COMMIT_ORDER方式計算last_committed,之後發生的事務再次對比已提交的事務的write_set,所以從庫並行執行的最大事務個數還受這個binlog_transaction_dependency_history_size 引數影響!
2.2 binlog_transaction_dependency_history_size引數
在程式碼實現上,MySQL採用一個vector的變數儲存已經提交的事務的HASH值(也就是writeset方式),所有已經提交的事務的所修改的主鍵和非空的UniqueKey的值經過HASH後與該vector中的值對比,由此來判斷當前提交的事務是否與最近一段時間已經提交的事務更新了同一行,並以此確定依賴關係。
該向量的大小由引數binlog_transaction_dependency_history_size控制,取值範圍為1-1000000 ,初始預設值為25000
2.3在計算writeset的時候,庫名+表名+主鍵+唯一鍵(有的話),為什麼需要加唯一鍵,
因為如果某個表主鍵為id ,唯一鍵為a,  主庫執行:session A先 執行update t1 set  a=6  where  id=1; session B 執行update t1 set a=1 where id=2,, 那麼如果你在計算writeset的時候沒有考慮唯一鍵,那麼這兩個session的事務可能會在從庫並行執行,就有可能sesstion B先執行而導致唯一鍵衝突而失敗!
2.4對於沒有主鍵的表 ,或者是有外來鍵約束的表,writeset策略是沒法並行的,也會暫時退化為單執行緒模型!
因為wirteset是透過 庫名+表名+主鍵值+(唯一鍵名字和非空鍵值)來確定的唯一性的,
如果你沒有主鍵,那麼你不能保證算出來的hash 值是唯一的,因為唯一鍵可以為空,所以沒有主鍵是不能用writeset的。又因為如果表上有外來鍵,級聯更新的行不會記錄到binlog中,這樣的衝突檢測就不準確!
三:影響並行事務的多少的引數:
3.1針對commit_order的方式的並行複製策略,可以透過修改如下兩個引數來影響併發的事務個數!
藉助組提交,同一個組的last committed值一樣,
1) binlog_group_commit_sync_delay 引數,表示延遲多少微秒後才呼叫 fsync;
2)binlog_group_commit_sync_no_delay_count 引數,表示累積多少次以後才呼叫fsync。這兩個引數是用於故意拉長 binlog 從 write 到 fsync的時間,以此減少 binlog 的寫盤次數。在 MySQL 5.7 的並行複製策略裡(COMMIT_ORDER方式),它們可以用來製造更多的“同時處於 prepare 階段的事務”。這樣就增加了備庫複製的並行度。
3.2針對writeset的並行複製方式:
binlog_transaction_dependency_history_size引數,控制最近一段時間已經提交的事務的個數,這個引數越大,理論上writeset的並行複製的事務可能會越多!
小結:不管是COMMIT_ORDER方式還是writeset方式的並行策略,從庫都是判斷last_committed是不是一樣來決定事務是不是可以並行複製的;不同的複製策略只不過主庫計算last_committed的方式不一樣;writeset的力度更細,


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29654823/viewspace-2767695/,如需轉載,請註明出處,否則將追究法律責任。

相關文章