????今天主要剖析一下MySQL 5.7增強(qiáng)半同步的AFTER SYNC和AFTER COMMIT的區(qū)別。
????如果我們生產(chǎn)庫(kù)對(duì)數(shù)據(jù)的一致性要求比較高,那么我們一般會(huì)開(kāi)啟了半同步復(fù)制,但在MySQL5.5/5.6里,會(huì)存在數(shù)據(jù)不一致的風(fēng)險(xiǎn)。比如有如下場(chǎng)景,客戶(hù)端提交了一個(gè)事務(wù),master把binlog發(fā)送給slave,在發(fā)送的期間,網(wǎng)絡(luò)出現(xiàn)波動(dòng),此時(shí)Binlog Dump線程發(fā)送就會(huì)卡住,要等待slave把binlog寫(xiě)到本地的relay-log里,然后給master一個(gè)反饋,等待的時(shí)間以rpl_semi_sync_master_timeout參數(shù)為準(zhǔn),默認(rèn)為10秒。在這等待的10秒鐘里,在其他會(huì)話(huà)里,查看剛才的事務(wù)是可以看見(jiàn)的,此時(shí)一旦master發(fā)生宕機(jī),由于binlog沒(méi)有發(fā)送給slave,前端app切到slave查看,就會(huì)發(fā)現(xiàn)剛才已提交的事務(wù)不見(jiàn)了。盜用兩張圖講解一下兩者的區(qū)別。
- AFTER SYNC
after sync是MySQL5.7官方新加的用以解決MySQL5.6半同步缺陷的選項(xiàng),也是官方推薦的方式。下面我結(jié)合圖來(lái)說(shuō)明一下AFTER SYNC是怎么回事。
image
????實(shí)際上,客戶(hù)端發(fā)出commit請(qǐng)求后,在主庫(kù)上寫(xiě)入binlog并推送給slave,slave接收到binlog并寫(xiě)入relaylog,發(fā)送ACK確認(rèn)已經(jīng)接收binlog后,master在引擎層commit,客戶(hù)端接收commit完成,此時(shí)其他會(huì)話(huà)才可以看見(jiàn)已提交的數(shù)據(jù)。
????故障分析:假設(shè)master在接收ACK確認(rèn)時(shí)宕機(jī),因?yàn)樵谝鎸硬](méi)有提交,HA切換到從庫(kù),因?yàn)閎inlog已經(jīng)寫(xiě)入從庫(kù)的relaylog,因此不會(huì)造成數(shù)據(jù)丟失,個(gè)人認(rèn)為是目前比較完美的解決方式。
- AFTER COMMIT
image
????after commit是MySQL5.6半同步參數(shù),區(qū)別于after sync,after sync是在接收ack確認(rèn)以后主庫(kù)在引擎層做提交,而after commit是先在引擎層做提交后等待ACK確認(rèn)。因此,在寫(xiě)入數(shù)據(jù)后并且在從庫(kù)確認(rèn)之前,其他的客戶(hù)端可以看到在這一事務(wù)。
????故障分析:
1.binlog 未發(fā)送到從庫(kù):
????事務(wù)B獲取到事務(wù)A提交的內(nèi)容, 此時(shí)宕機(jī)故障切換到slave,事務(wù)B獲取到的內(nèi)容卻丟失了。事務(wù)A commit沒(méi)有收到反饋信息(則需要業(yè)務(wù)判斷了)。
2.binlog 已經(jīng)發(fā)送給從庫(kù) :
????事務(wù)B獲取到事務(wù)A提交的內(nèi)容,故障切換到salve ,B仍然獲取到A提交的內(nèi)容,沒(méi)毛病。事務(wù)A commit沒(méi)有收到反饋信息,若重新執(zhí)行該事務(wù),則相當(dāng)于執(zhí)行兩次A事務(wù)(則需要業(yè)務(wù)判斷了)。
dump thread過(guò)程分析:
- mysql5.6版本之前:
1. master dump thread 發(fā)送binlog events 給 slave 的IO thread,等待 slave 的ack反饋
2. slave 接受binlog events 寫(xiě)入relay log ,返回 ack 消息給master dump thread
3. master dump thread 收到ack消息,給session返回commit ok,然后繼續(xù)發(fā)送寫(xiě)一個(gè)事務(wù)的binlog。
- mysql5.7之后新增ack線程:
1. master dump thread 發(fā)送binlog events 給 slave 的IO thread,開(kāi)啟ack線程等待 slave 的ack反饋,dump 線程繼續(xù)向slaveIO thread發(fā)送下一個(gè)事務(wù)的binlog。
2. slave 接受binlog events 寫(xiě)入relay log ,返回 ack 消息給master ack線程,然后給session返回commit ok。
過(guò)程總結(jié):
1.Master在收到slave的應(yīng)答后才Commit事務(wù)--after_sync(5.6上Master在commit后,才等待Slave的應(yīng)答--after commit).
因此在確認(rèn)事務(wù)復(fù)制到Slave上之前,并發(fā)的事務(wù)看不到當(dāng)前事務(wù)的數(shù)據(jù).當(dāng)Master出現(xiàn)故障時(shí),所有已經(jīng)提交的事務(wù)都復(fù)制到了Slave上.
2.缺省采用無(wú)數(shù)據(jù)丟失的應(yīng)答等待機(jī)制after_sync。用戶(hù)也可以選擇使用5.6的應(yīng)答等待機(jī)制after_commit
設(shè)置方法:
mysql> SET rpl_semi_sync_master_wait_point= AFTER_SYNC;
Master接收到N個(gè)slave的應(yīng)答后,才commit 事務(wù).
用戶(hù)可以設(shè)置應(yīng)答Slave的數(shù)量:
mysql> SET GLOBAL rpl_semi_sync_master_wait_for_slave_count= N;

