mysql半同步相關問題:最近有dba業務場景對數據質量要求比較高,而現在的主備切換可能會發生最後一個事務的數據質量問題,依賴半同步的超時時間來更大的保證數據質量。
半同步原理
半同步和非半同步最大的區別就是client 遞交commit後是立馬返回ack還是主備同步後再返回ack,如下圖所示:
1.半同步時接受到1個備庫的ack就會給客戶端返回commit success,全同步就需要所有備庫都返回ack才返回commit success
2.下圖是半同步時主庫需要操作的流程,大致分為解析sql、寫binlog、commit事務、等待主備同步、返回commit success
註意:這裡寫瞭binlog主庫立馬就遞交事務瞭,然後一直等待主備同步好的ack
上圖中的半同步存在如下問題:
客戶端事務在存儲引擎層提交後,在得到從庫確認的過程中,主庫宕機瞭,此時,可能的情況有兩種
1.事務還沒發送到從庫上
此時,客戶端會收到事務提交失敗的信息,客戶端會重新提交該事務到新的主上,當宕機的主庫重新啟動後,以從庫的身份重新加入到該主從結構中,會發現,該事務在從庫中被提交瞭兩次,一次是之前作為主的時候,一次是被新主同步過來的。
2.事務已經發送到從庫上
此時,從庫已經收到並應用瞭該事務,但是客戶端仍然會收到事務提交失敗的信息,重新提交該事務到新的主上。
在5.7中(集團alisql5.6也已有這個參數)引入瞭一種新的半同步方案:Loss-Less半同步復制。
引入瞭一個新的參數rpl_semi_sync_master_wait_point進行控制上圖中“Waiting Slave dump”和“Storage Commit”的先後順序。
AFTER_SYNC:Waiting Slave dump在Storage Commit之前,如下圖所示:
AFTER_COMMIT:跟上圖一樣,如下所示
註:因為發生半同步降級的主要原因是主備同步不成功造成的,5.7中把等待同步放在storage commit(執行完此句後會記binlog和數據到磁盤)之前可以很好的解掉上述兩個問題中的數據重復問題。
關心的半同步時間點
下面是切換時候關註的幾個點,5.6的資料庫
1.在半同步模式下
@startuml == 事務開始 == client -> client: sql組成一個事務 client -> 主庫: 事務commit 1. 主庫 -> 主庫:記binlog 主庫 -> 備庫:主備同步 2. 主庫 -> 主庫:commit事務 備庫 -> 備庫:同步數據 主庫 -> 主庫:等待同步 備庫 -> 主庫: 同步ack 3. 主庫 -> client:commit success信號 4. == 事務結束 == @enduml
以下都假設sync_binlog=1,rpl_semi_sync_master_wait_point=AFTER_COMMIT的時候
1.client遞交瞭commit此時發生瞭主備切換,這時候主備數據是一致的,因為主備都沒記binlog,此時切換後沒有數據做回滾回補,也不會有數據質量問題,但是應用發生commit錯誤,在恢復後的新主庫重新做此事務,無數據丟失情況
2.主備同步過程中發生瞭crash:主庫記binlog瞭,備庫沒有記relaylog,此時老主恢復後會HA將老主庫的數據回滾掉,在老備庫中回補,無數據質量問題,但是應用發生ack錯誤,在恢復後的新主庫上重新執行此事務,待老主恢復後進行回滾,在新主進行回補,此時新主就會產生數據重復(幾率較大因為主備同步失敗幾率較大,受網絡等影響)
3.都落盤備庫返回ack時主備切換:主備都落盤瞭,不會進行回滾回補,無數據質量問題,但是ack失敗,切換恢復後應用重新執行此事務,引發數據重復(幾率較小,因為主要影響和耗時在主備同步階段)
4.事務結束時發生切換,此時跟非回滾回補時候一樣,不進行回滾回補,無數據質量問題
以下都假設sync_binlog=1,rpl_semi_sync_master_wait_point=AFTER_SYNC的時候
上面的2中,主庫記binlog瞭,備庫沒同步成功,主庫發生crash,此時主庫未commit事務,機器重啟後會恢復binlog中的事務,commit事務,HA回滾掉老主庫這條事務,不回補,應用未ack成功重試,此時無數據重復問題,解決瞭上面2中的問題,前提是HA不回補
上面3中,主庫記binlog,備庫記relaylog後,但未commit事務成功就crash瞭,機器恢復後恢復binlog中未commit的事務,HA無需回滾回補,應用未ack成功重試,從而發生數據重復(幾率較小,因為主要影響和耗時在主備同步階段)
從上面兩個推理可見:
AFTER_COMMIT和AFTER_SYNC都有可能發生數據重復的問題,但是使用AFTER_SYNC會大大減少數據重復問題
AFTER_COMMIT和AFTER_SYNC性能差別:
AFTER_COMMIT:記binlog後就commit事務,釋放commit鎖,但等待同步的過程中下一個事務可以進來瞭
AFTER_SYNC:要等待同步之後才commit事務,釋放commit鎖,這時下一個事務才能進來,性能會減低很多
2.在半同步發生降級後產生主備切換
跟非半同步模式下切換一樣,可能發生數據質量問題
開啟半同步時候的問題與解決
基於5.6的庫,隻靠半同步超時時間來保證主備的一致性
發生commit失敗時候,不管發生切換還是未發生切換都可能會產生數據重復的問題,因為不能保證此時數據有沒有落盤
半同步又發生主備切換時候,不管觸發回滾回補還是無需進行回滾回補都有可能產生數據重復問題,但不會出現數據丟失問題
解決:
因為不管回滾回補都可能會出現數據重復的問題,所以考慮的隻回滾不回補方案不可行
開啟MP模式,發生降級時候開啟MP模式,進入MP模式後引發切換,隻回滾不回補,此方案對發生回滾回補觸發的數據重復問題可解,但是對未觸發回滾回補的情況還是不可解,且觸發MP後引發切換,這樣會導致應用不可用時間太長
應用進行改造,發生commit失敗時重新commit前先檢查一下上次commit是否落盤,問題可解,但是需要應用改造
半同步公認的問題(不開MP):
超時時間直接與資料庫rt掛鉤,設置不當嚴重影響性能,超時時間設置為業務能接受的 db 的最大 rt,必須保證 semi-sync 超時降級的場景下不影響應用可用性
超時發生降級變為異步可能產生數據質量問題。