簡(jiǎn)單談?wù)凪ySQL的半同步復(fù)制
簡(jiǎn)介
MySQL通過(guò)復(fù)制(Replication)實(shí)現(xiàn)存儲(chǔ)系統(tǒng)的高可用。目前,MySQL支持的復(fù)制方式有:
- 異步復(fù)制(Asynchronous Replication):原理最簡(jiǎn)單,性能最好。但是主備之間數(shù)據(jù)不一致的概率很大。
- 半同步復(fù)制(Semi-synchronous Replication):相比異步復(fù)制,半同步復(fù)制犧牲了一定的性能,提升了主備之間數(shù)據(jù)的一致性(有一些情況還是會(huì)出現(xiàn)主備數(shù)據(jù)不一致)。
- 組復(fù)制(Group Replication):基于Paxos算法實(shí)現(xiàn)分布式數(shù)據(jù)復(fù)制的強(qiáng)一致性。只要大多數(shù)機(jī)器存活就能保證系統(tǒng)可用。相比半同步復(fù)制,Group Replication的數(shù)據(jù)一致性和系統(tǒng)可用性更高。
本文主要討論MySQL半同步復(fù)制。
半同步復(fù)制的基本流程
MySQL半同步復(fù)制的實(shí)現(xiàn)是建立在MySQL異步復(fù)制的基礎(chǔ)上的。MySQL支持兩種略有不同的半同步復(fù)制:AFTER_SYNC和AFTER_COMMIT(受rpl_semi_sync_master_wait_wait_point控制)。
開(kāi)啟半同步復(fù)制時(shí),Master在返回之前會(huì)等待Slave的響應(yīng)或超時(shí)。當(dāng)Slave超時(shí)時(shí),半同步復(fù)制退化成異步復(fù)制。這也是MySQL半同步復(fù)制存在的一個(gè)問(wèn)題。本文不討論Salve超時(shí)的情形(不討論異步復(fù)制)。
半同步復(fù)制AFTER_SYNC模式的基本流程
AFTER_SYNC模式是MySQL 5.7才支持的半同步復(fù)制方式,也是MySQL5.7默認(rèn)的半同步復(fù)制方式:
- 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).
半同步復(fù)制AFTER_COMMIT模式的基本流程
MySQL 5.5和5.6的半同步復(fù)制只支持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兩種方式的小結(jié)
AFTER_SYNC: 日志復(fù)制到Slave之后,Master再commit。
所有在master上commit的事務(wù)都已經(jīng)復(fù)制到slave。
所有已經(jīng)復(fù)制到slave的事務(wù)在master不一定commit了(比如,master將日志復(fù)制到slave之后,在commit之前宕機(jī)了)
AFTER_COMMIT:Master commit之后再將日志復(fù)制到Slave。
所有master上commit的事務(wù)不一定復(fù)制到slave。(比如,master commit之后,還沒(méi)來(lái)得及將日志復(fù)制到slave就宕機(jī)了)
所有已經(jīng)復(fù)制到slave的事務(wù)在master上一定commit了。
很明顯,AFTER_COMMIT在master宕機(jī)的情況下,無(wú)法保證數(shù)據(jù)的一致性(master commit之后,還沒(méi)來(lái)得及將日志復(fù)制到slave就宕機(jī)了)。本文接下來(lái)只討論AFTER_SYNC模式。
MySQL5.7.3開(kāi)始支持配置半同步復(fù)制等待Slave應(yīng)答的個(gè)數(shù):rpl_semi_sync_master_wait_slave_count 。
AFTER_SYNC模式下的異常情況分析
異常情況1:master宕機(jī)后,主備切換。
master執(zhí)行事務(wù)T,在將事務(wù)T的binlog刷到硬盤(pán)之前,master發(fā)生宕機(jī)。slave升級(jí)為master。master重啟后,crash recovery會(huì)對(duì)事務(wù)T進(jìn)行回滾。主備數(shù)據(jù)一致。
master執(zhí)行事務(wù)T,在將事務(wù)T的binlog刷到硬盤(pán)之后,收到slave的ACK之前,master發(fā)生宕機(jī)(存在pendinglog)。slave升級(jí)為master。
2.1 slave還沒(méi)有收到事務(wù)T的binlog,master重啟后,crash recovery會(huì)直接提交pendinglog。主備數(shù)據(jù)不一致。
2.2 slave已經(jīng)收到事務(wù)T的binlog。主備數(shù)據(jù)一致。
異常情況2:master宕機(jī)后,不切換主機(jī)。只需考慮異常情況1中的2.1。
master重啟后,直接提交pendinglog,此時(shí),主備數(shù)據(jù)不一致:
slave連接上master,通過(guò)異步復(fù)制的方式獲得事務(wù)T的binlog。主備數(shù)據(jù)一致。
slave還沒(méi)來(lái)得及復(fù)制事務(wù)T的binlog,如果master又發(fā)生宕機(jī),磁盤(pán)損壞。主備數(shù)據(jù)不一致,事務(wù)T的數(shù)據(jù)丟失。
異常情況處理
從上面異常情況的簡(jiǎn)單分析我們得知,半同步復(fù)制需要處理master宕機(jī)后重啟存在pendinglog(slave沒(méi)有應(yīng)答的binlog)的特殊情況。
針對(duì)master宕機(jī)后,不進(jìn)行主備切換的情形:
在crash recovery之后,master等到slave的連接和復(fù)制,直到至少有一個(gè)slave復(fù)制了所有已提交的事務(wù)的binlog。(SHOW MASTER STATUS on master and SELECT master_pos_wait() on slave)。
針對(duì)master宕機(jī)后,進(jìn)行主備切換的情形:
舊master重啟后,在crash recovery時(shí),對(duì)pendinglog進(jìn)行回滾。(人工截?cái)鄊aster的binlog未復(fù)制的部分?)
思考
為什么master重啟之后,crash recovery的過(guò)程中,是直接commit pendinglog,而不是重試請(qǐng)求slave的應(yīng)答呢?
MySQL的異步復(fù)制和半同步復(fù)制都是由slave觸發(fā)的,slave主動(dòng)去連接master同步binlog。
沒(méi)有發(fā)生主備切換,機(jī)器重啟后無(wú)法知道哪臺(tái)機(jī)器是slave。
如果發(fā)生主備切換,它已經(jīng)不是master了,則不會(huì)再有slave連上來(lái)。如果繼續(xù)等待,則無(wú)法正常運(yùn)行。
總結(jié)
MySQL半同步復(fù)制存在以下問(wèn)題:
- 當(dāng)Slave超時(shí)時(shí),會(huì)退化成異步復(fù)制。
- 當(dāng)Master宕機(jī)時(shí),數(shù)據(jù)一致性無(wú)法保證,需要人工處理。
- 復(fù)制是串行的。
正因?yàn)镸ySQL在主備數(shù)據(jù)一致性存在著這些問(wèn)題,影響了互聯(lián)網(wǎng)業(yè)務(wù)7*24的高可用服務(wù),因此各大公司紛紛祭出自己的“補(bǔ)丁”:騰訊的TDSQL、微信的PhxSQL、阿里的AliSQL、網(wǎng)易的InnoSQL。
MySQL官方已經(jīng)在MySQL5.7推出新的復(fù)制模式——MySQL Group Replication。
參考文獻(xiàn)
MySQL半同步復(fù)制的數(shù)據(jù)一致性探討
MySQL High Availability Solutions
相關(guān)文章
解決mysql創(chuàng)建數(shù)據(jù)庫(kù)后出現(xiàn):Access denied for user ''root''@''%'' to dat
這篇文章主要給大家介紹了如何解決mysql在創(chuàng)建數(shù)據(jù)庫(kù)后出現(xiàn):Access denied for user 'root'@'%' to database 'xxx'的錯(cuò)誤提示,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-05-05最新Navicat?15?for?MySQL破解+教程?正確破解步驟
Navicat?for?MySQL是一個(gè)針對(duì)MySQL數(shù)據(jù)庫(kù)而開(kāi)發(fā)的第三方mysql管理工具,該軟件可以用于?MySQL?數(shù)據(jù)庫(kù)服務(wù)器版本?3.21?或以上的和?MariaDB?5.1?或以上,這篇文章主要介紹了最新Navicat?15?for?MySQL破解+教程?正確破解步驟,需要的朋友可以參考下2023-04-04mysql創(chuàng)建函數(shù)出現(xiàn)1418錯(cuò)誤的解決辦法
本篇文章是對(duì)在Mysql中創(chuàng)建函數(shù)報(bào)“ERROR 1418”的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06MySQL數(shù)據(jù)庫(kù)安全設(shè)置與注意事項(xiàng)小結(jié)
現(xiàn)在很多朋友使用mysql數(shù)據(jù)庫(kù),為了安全考慮我們就需要考慮到mysql的安全問(wèn)題,例如需要將mysql以普通用戶(hù)權(quán)限運(yùn)行,就算出問(wèn)題了有了root也不能控制系統(tǒng)2013-08-08Windows 8.1下MySQL5.7 忘記root 密碼的解決方法
最近學(xué)習(xí)碰到了一件挺令人尷尬的事情,我把MySQL的密碼給忘記了,所以MySQL登錄不進(jìn)去。在網(wǎng)上找的解決方案都不靠譜,下面小編給大家分享Windows 8.1下MySQL5.7 忘記root 密碼的解決方法,需要的朋友一起看看吧2017-07-07mysql source 命令導(dǎo)入大的sql文件的方法
本文將詳細(xì)介紹mysql source 命令導(dǎo)入大的sql文件的方法;需要的朋友可以參考下2012-11-11MySQL數(shù)據(jù)庫(kù)優(yōu)化詳解
這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)優(yōu)化的方方面面,各種小技巧,需要的朋友可以參考下2014-08-08