簡介
MySQL通過復制(Replication)實現存儲系統的高可用。目前,MySQL支持的復制方式有:
- 異步復制(Asynchronous Replication):原理最簡單,性能最好。但是主備之間數據不一致的概率很大。
- 半同步復制(Semi-synchronous Replication):相比異步復制,半同步復制犧牲了一定的性能,提升了主備之間數據的一致性(有一些情況還是會出現主備數據不一致)。
- 組復制(Group Replication):基于Paxos算法實現分布式數據復制的強一致性。只要大多數機器存活就能保證系統可用。相比半同步復制,Group Replication的數據一致性和系統可用性更高。
本文主要討論MySQL半同步復制。
半同步復制的基本流程
MySQL半同步復制的實現是建立在MySQL異步復制的基礎上的。MySQL支持兩種略有不同的半同步復制:AFTER_SYNC和AFTER_COMMIT(受rpl_semi_sync_master_wait_wait_point控制)。
開啟半同步復制時,Master在返回之前會等待Slave的響應或超時。當Slave超時時,半同步復制退化成異步復制。這也是MySQL半同步復制存在的一個問題。本文不討論Salve超時的情形(不討論異步復制)。
半同步復制AFTER_SYNC模式的基本流程
AFTER_SYNC模式是MySQL 5.7才支持的半同步復制方式,也是MySQL5.7默認的半同步復制方式:
- Prepare the transaction in the storage engine(s).
- Write the transaction to the binlog, flush the binlog to disk.
- Wait for at least one slave to acknowledge the reception for the binlog events for the transaction.
- Commit the transaction to the storage engine(s).
半同步復制AFTER_COMMIT模式的基本流程
MySQL 5.5和5.6的半同步復制只支持AFTER_COMMIT:
- Prepare the transaction in the storage engine(s).
- Write the transaction to the binlog, flush the binlog to disk.
- Commit the transaction to the storage engine(s).
- Wait for at least one slave to acknowledge the reception for the binlog events for the transaction.
AFTER_SYNC和AFTER_COMMIT兩種方式的小結
AFTER_SYNC: 日志復制到Slave之后,Master再commit。
所有在master上commit的事務都已經復制到slave。
所有已經復制到slave的事務在master不一定commit了(比如,master將日志復制到slave之后,在commit之前宕機了)
AFTER_COMMIT:Master commit之后再將日志復制到Slave。
所有master上commit的事務不一定復制到slave。(比如,master commit之后,還沒來得及將日志復制到slave就宕機了)
所有已經復制到slave的事務在master上一定commit了。
很明顯,AFTER_COMMIT在master宕機的情況下,無法保證數據的一致性(master commit之后,還沒來得及將日志復制到slave就宕機了)。本文接下來只討論AFTER_SYNC模式。
MySQL5.7.3開始支持配置半同步復制等待Slave應答的個數:rpl_semi_sync_master_wait_slave_count 。
AFTER_SYNC模式下的異常情況分析
異常情況1:master宕機后,主備切換。
master執行事務T,在將事務T的binlog刷到硬盤之前,master發生宕機。slave升級為master。master重啟后,crash recovery會對事務T進行回滾。主備數據一致。
master執行事務T,在將事務T的binlog刷到硬盤之后,收到slave的ACK之前,master發生宕機(存在pendinglog)。slave升級為master。
2.1 slave還沒有收到事務T的binlog,master重啟后,crash recovery會直接提交pendinglog。主備數據不一致。
2.2 slave已經收到事務T的binlog。主備數據一致。
異常情況2:master宕機后,不切換主機。只需考慮異常情況1中的2.1。
master重啟后,直接提交pendinglog,此時,主備數據不一致:
slave連接上master,通過異步復制的方式獲得事務T的binlog。主備數據一致。
slave還沒來得及復制事務T的binlog,如果master又發生宕機,磁盤損壞。主備數據不一致,事務T的數據丟失。
異常情況處理
從上面異常情況的簡單分析我們得知,半同步復制需要處理master宕機后重啟存在pendinglog(slave沒有應答的binlog)的特殊情況。
針對master宕機后,不進行主備切換的情形:
在crash recovery之后,master等到slave的連接和復制,直到至少有一個slave復制了所有已提交的事務的binlog。(SHOW MASTER STATUS on master and SELECT master_pos_wait() on slave)。
針對master宕機后,進行主備切換的情形:
舊master重啟后,在crash recovery時,對pendinglog進行回滾。(人工截斷master的binlog未復制的部分?)
思考
為什么master重啟之后,crash recovery的過程中,是直接commit pendinglog,而不是重試請求slave的應答呢?
MySQL的異步復制和半同步復制都是由slave觸發的,slave主動去連接master同步binlog。
沒有發生主備切換,機器重啟后無法知道哪臺機器是slave。
如果發生主備切換,它已經不是master了,則不會再有slave連上來。如果繼續等待,則無法正常運行。
總結
MySQL半同步復制存在以下問題:
- 當Slave超時時,會退化成異步復制。
- 當Master宕機時,數據一致性無法保證,需要人工處理。
- 復制是串行的。
正因為MySQL在主備數據一致性存在著這些問題,影響了互聯網業務7*24的高可用服務,因此各大公司紛紛祭出自己的“補丁”:騰訊的TDSQL、微信的PhxSQL、阿里的AliSQL、網易的InnoSQL。
MySQL官方已經在MySQL5.7推出新的復制模式——MySQL Group Replication。
參考文獻
MySQL半同步復制的數據一致性探討
MySQL High Availability Solutions
Loss-less Semi-Synchronous Replication on MySQL 5.7.2
Enhanced semisync replication
您可能感興趣的文章:- MYSQL 完全備份、主從復制、級聯復制、半同步小結
- MySQL半同步復制原理配置與介紹詳解
- Mysql半同步復制原理及問題排查
- 深入解析半同步與異步的MySQL主從復制配置
- 詳解MySQL的半同步