看到很多MySql事務(wù)的兩階段提交的文章嘴拢,感覺大部分還是八股文唇敞,這里記錄一下自己心得窿撬。
redolog和binlog是什么
具體是什么启昧,以及區(qū)別這里不再贅述,可以參見這個(gè):為什么寫入redo log和bin log要用兩個(gè)階段提交呢
注意劈伴,redolog記錄的是數(shù)據(jù)修改(如set count = 18),binlog記錄的是sql(如update count = count +1)
顯然,從redolog中是恢復(fù)不了binlog(sql) 的(只有數(shù)據(jù)的前后狀態(tài)跛璧,不知中間具體操作)
但是严里,理論上,從binlog中可以恢復(fù)redolog追城,但是要結(jié)合之前的數(shù)據(jù)狀態(tài)刹碾,這個(gè)過程其實(shí)就是重現(xiàn)redolog prepare階段的計(jì)算。
兩階段步驟過程
圖來源:為什么寫入redo log和bin log要用兩個(gè)階段提交呢
如果簡單理解座柱,就是對于客戶端的一個(gè)事務(wù)請求:redolog prepare——binlog——redolog commit迷帜。
為什么要兩階段
其實(shí)這個(gè)問題更準(zhǔn)確的說法應(yīng)該是——為什么redolog要分兩階段標(biāo)記?
回答這個(gè)問題之前色洞,我們有幾個(gè)前提要了解一下:
1)我們要保證binlog的完整性
binlog要用于宕機(jī)后恢復(fù)戏锹,和主從復(fù)制在slave機(jī)上復(fù)現(xiàn)master機(jī)記錄,前文已經(jīng)提到:從redolog中是恢復(fù)不了binlog(sql)火诸,這要求“宕機(jī)之前的binlog記錄要完整”
2)第一步就crash的情況锦针,不用考慮宕機(jī)恢復(fù)
binlog和redolog都還沒開始記錄,crash了置蜀,不用管奈搜。
因?yàn)槎叨紱]記錄,那么恢復(fù)時(shí)此次事務(wù)沒有留下任何記錄盯荤,滿足原子性——要么做完馋吗,要么沒做,此時(shí)這次事務(wù)是對應(yīng)于沒做的情況秋秤,不影響耗美。
這提示我們,無論是用多少階段提交航缀,第一步就crash的情況商架,不用考慮宕機(jī)恢復(fù),因?yàn)槭聞?wù)完全沒有執(zhí)行
一階段真的無法保持一致嗎
知道了這些前提芥玉,讓我們再來假設(shè)一下如果redolog只用一次標(biāo)記——直接commit蛇摸,中間發(fā)生crash(宕機(jī)/線程掛了)會發(fā)生什么。
顯然灿巧,根據(jù)binlog和redolog的操作順序赶袄,有兩種情況:
-
先redolog commit,再寫binlog
如果寫binlog過程中發(fā)生crash抠藕,因?yàn)閞edolog中恢復(fù)不了binlog(前面已經(jīng)說過這種情況)饿肺,宕機(jī)后二者內(nèi)容不一致,恢復(fù)時(shí)binlog記錄也找不回盾似。
那么是否意味著二者無法保持一致性了呢敬辣?
并不是,可以考慮這么干:redolog現(xiàn)在就是比binlog多了最新的事務(wù)內(nèi)容而已,刪掉對應(yīng)的不就行了:
對比redolog和binlog的記錄溉跃,發(fā)現(xiàn)redolog的最新txid比binlog大村刨,說明binlog寫一半停機(jī)了,所以刪掉redolog中這個(gè)txid對應(yīng)的記錄撰茎,二者又保持了一致性嵌牺,只是是恢復(fù)到該事務(wù)之前的狀態(tài)。 -
先寫binlog龄糊,再redolog commit
如果redolog commit過程中發(fā)生crash逆粹,理論上是可以從binlog中恢復(fù)redolog內(nèi)容的,然后提交炫惩,這就保持了一致性僻弹。
或者對比對比redolog和binlog的記錄,將binlog存在但redolog不存在的記錄刪除诡必,也能恢復(fù)一致性奢方。
前者的一致性是事務(wù)執(zhí)行之后的狀態(tài),后者是事務(wù)執(zhí)行之前的狀態(tài)爸舒。
可以看到蟋字,無論是哪種方式,都是可以保持二者一致性的扭勉,只是恢復(fù)時(shí)鹊奖,抹去or填平不一致需要較重的成本——回滾or追加binlog redolog內(nèi)容。
兩階段提交以極低成本實(shí)現(xiàn)了crash-safe
那么兩階段在應(yīng)對crash情況時(shí)的恢復(fù)成本如何呢涂炎?
redolog prepare——binlog——redolog commit
1)如果在寫binlog過程中宕機(jī)忠聚,重啟時(shí)發(fā)現(xiàn)binlog不完整,直接將redolog prepare的記錄刪除唱捣,恢復(fù)了事務(wù)執(zhí)行之前的數(shù)據(jù)一致性
2)如果在標(biāo)記redolog commit過程中宕機(jī)两蟀,重啟時(shí)發(fā)現(xiàn)binlog完整且redolog prepare,那么繼續(xù)宕機(jī)前的工作——標(biāo)記redolog commit即可震缭。
可以看到赂毯,兩階段的策略,“恢復(fù)一致性成本”很低拣宰,不涉及binlog和真正的redolog(非prepare commit標(biāo)記)的添加or刪除(回滾)党涕,僅僅是重新處理redolog flag而已。
總結(jié)
一階段同樣可以實(shí)現(xiàn)crash-safe巡社,但是成本高昂——要去寫binlog/redolog記錄膛堤,兩階段以極低成本實(shí)現(xiàn)了crash-safe,所以是更好的方案晌该。