問題1:Mysql是如何保證不丟數(shù)據(jù)的?
眾所周知,事務(wù)一旦提交,則對數(shù)據(jù)的改變將永久有效,這是數(shù)據(jù)庫持久性的特性.那么Mysql是如何做到不丟數(shù)據(jù)的?什么是commit?事務(wù)commit時Mysql又做了什么?
數(shù)據(jù)的持久性機(jī)制依賴server層的binlog以及InnoDB存儲引擎層的redolog.
事務(wù)的commit操作本身,包含兩個階段的處理:
準(zhǔn)備階段:
server調(diào)用InnoDB寫入redolog
完成階段:
1.server寫入binlog
2.server調(diào)用InnoDB,寫入commit標(biāo)簽(在redolog中)
其中,事務(wù)提交是否成功,以binlog是否成功落盤為準(zhǔn).
場景1:
準(zhǔn)備階段失敗,redolog沒有寫入,則提交失敗,且數(shù)據(jù)一致.
場景2:
準(zhǔn)備階段成功,redolog寫入,完成階段server寫入binlog失敗,則提交失敗.此時數(shù)據(jù)不一致(存在redolog但不存在binlog).宕機(jī)恢復(fù)時,因為不存在binlog,因此需要對事務(wù)進(jìn)行回滾.
場景3
完成階段server寫入binlog成功,server調(diào)用InnoDB,寫入commit標(biāo)簽失敗,則提交成功.此時數(shù)據(jù)不一致(redolog中缺少commit標(biāo)志).宕機(jī)恢復(fù)時,補(bǔ)償寫入commit標(biāo)簽以及后續(xù)處理.
總結(jié),提交時的兩階段處理,可以保證數(shù)據(jù)的持久性,以及binlog和redolog內(nèi)部的一致性.
問題2:如何提高M(jìn)ysql可用性?
Mysql的ACID的特性保證了其單機(jī)的可靠性,但是存在單點風(fēng)險.
由此引出了主從架構(gòu)和復(fù)制的概念.
所謂復(fù)制,就是slave負(fù)責(zé)從master讀取binlog,并寫入自己的relaylog中,之后通過relaylog進(jìn)行重放,已達(dá)到數(shù)據(jù)同步的目的.
問題3:Mysql支持哪些復(fù)制以及對應(yīng)的優(yōu)缺點?
生產(chǎn)環(huán)境中常見的復(fù)制包含異步復(fù)制和半同步復(fù)制兩種.
異步復(fù)制就是在master事務(wù)提交后,立即給客戶端返回結(jié)果,將復(fù)制操作變?yōu)楫惒降?優(yōu)點是不會影響客戶端的響應(yīng)時效,缺點是無法保證主從間的數(shù)據(jù)一致性.如果master宕機(jī),則slave可能會丟失數(shù)據(jù).
半同步復(fù)制就是在事務(wù)提交后,結(jié)果返回給客戶端之前,增加了與slave見的復(fù)制和確認(rèn)過程,只有接到slave的ack后,才會返回給客戶端結(jié)果.相比異步復(fù)制,它增加了等待的時間,也即降低了客戶端響應(yīng)失效,但是保證了master與slave間的強(qiáng)一致性.
注意:如果master等待slave的ack時超時,則會降級為異步復(fù)制模式,所以生產(chǎn)中要將超時時間設(shè)置的足夠大,來保證半同步的有效性.
問題4:Mysql5.7之前半同步存在的問題?
Mysql5.7之前,半同步的復(fù)制流程為:
prepare(寫redolog)->寫binlog->寫commit標(biāo)志->復(fù)制->確認(rèn).
這對應(yīng)rpl_semi_sync_master_point=AFTER_COMMIT的配置.
復(fù)制發(fā)生在commit完成之后,因此在復(fù)制期間,客戶端拿到結(jié)果之前,事務(wù)結(jié)果已經(jīng)可見了.也就是說,其他會話會先于當(dāng)前會話看到事務(wù)結(jié)果.
為了解決這一問題,Mysql5.7增加了rpl_semi_sync_master_point=AFTER_SYNC的配置,將復(fù)制流程變?yōu)?
prepare(寫redolog)->寫binlog->復(fù)制->確認(rèn)->寫commit標(biāo)志.
也就是說復(fù)制和確認(rèn)發(fā)生在binlog寫入成功之后,InnoDBcommit之前,由此,在復(fù)制完成之前,其他會話不會看到當(dāng)前事務(wù)的結(jié)果.
問題5:主從架構(gòu)下,如何保證可用性的同時,確保數(shù)據(jù)一致性?
前文所述,事務(wù)的持久性是以binlog寫入是否成功為準(zhǔn)的.如果master在binlog寫入成功之后,復(fù)制之前發(fā)生宕機(jī),則slave沒有拿到master的binlog.此時如果為了高可用而進(jìn)行slave升主操作時,會導(dǎo)致丟數(shù)據(jù).
通常的解決方案是:在升主之前進(jìn)行主從之間的數(shù)據(jù)對比校驗,以確保數(shù)據(jù)一致性.
問題6:數(shù)據(jù)校驗期間Mysql不可寫如何解決?
通常通過多主從組,加數(shù)據(jù)分片和路由解決.當(dāng)某個master宕機(jī)時,將寫入請求導(dǎo)入另外的master,并在此期間對故障master進(jìn)行恢復(fù)和數(shù)據(jù)校驗.
另外,為了對機(jī)房斷電進(jìn)行容災(zāi),通常采用一機(jī)房雙master-slave,外加多機(jī)房的部署架構(gòu).