基于Redo Log和Undo Log的MySQL崩潰恢復流程

在之前的文章「簡單了解InnoDB底層原理」聊了一下MySQL的Buffer Pool。這里再簡單提一嘴,Buffer Pool是MySQL內存結構中十分核心的一個組成,你可以先把它想象成一個黑盒子。

黑盒下的更新數據流程

當我們查詢數據的時候,會先去Buffer Pool中查詢。如果Buffer Pool中不存在,存儲引擎會先將數據從磁盤加載到Buffer Pool中,然后將數據返回給客戶端;同理,當我們更新某個數據的時候,如果這個數據不存在于Buffer Pool,同樣會先數據加載進來,然后修改修改內存的數據。被修改過的數據會在之后統一刷入磁盤。

MySQL 崩潰恢復

這個過程看似沒啥問題,實則不講武德。假設我們修改Buffer Pool中的數據成功,但是還沒來得及將數據刷入磁盤MySQL就掛了怎么辦?按照上圖的邏輯,此時更新之后的數據只存在于Buffer Pool中,如果此時MySQL宕機了,這部分數據將會永久的丟失;

再者,我更新到一半突然發生錯誤了,想要回滾到更新之前的版本,該怎么辦?那不完犢子嗎,連數據持久化的保證、事務回滾都做不到還談什么崩潰恢復?

Redo Log & Undo Log

而通過MySQL能夠實現崩潰恢復的事實來看,MySQL必定實現了某些騷操作。沒錯,這就是接下來我們要介紹的另外的兩個關鍵功能,Redo LogUndo Log。

這兩種日志是屬于InnoDB存儲引擎的日志,和MySQL Server的Binlog不是一個維度的日志。

  1. Redo Log 記錄了此次事務「完成后」的數據狀態,記錄的是更新之「后」的值
  2. Undo Log 記錄了此次事務「開始前」的數據狀態,記錄的是更新之「前」的值

所以這兩種日志有明顯的區別,我用一種更加通俗的例子來解釋一下這兩種日志。

Redo Log就像你在命令行敲了很長的命令,敲回車執行,結果報錯了。此時我們只需要再敲個↑就會拿到上一條命令,再執行一遍即可。

Undo Log就像你剛剛在Git中Commit了一下,然后再做一個較為復雜的改動,但是改著改著你的心態崩了,不想要剛剛的改動了,于是直接git reset --hard $lastCommitId回到了上一個版本。

實現日志后的更新流程

有了Redo Log和Undo Log,我們再將上面的那張圖給完善一下。

MySQL 崩潰恢復

首先,更新數據還是會判斷數據是否存在于Buffer Pool中,不存在則加載。上面我們提到了回滾的問題,在更新Buffer Pool中的數據之前,我們需要先將該數據事務開始之前的狀態寫入Undo Log中。假設更新到一半出錯了,我們就可以通過Undo Log來回滾到事務開始前。

然后執行器會更新Buffer Pool中的數據,成功更新后會將數據最新狀態寫入Redo Log Buffer中。因為一個事務中可能涉及到多次讀寫操作,寫入Buffer中分組寫入,比起一條條的寫入磁盤文件,效率會高很多。

redo-log-buffer

那為什么Undo Log不也搞一個Undo Log Buffer,也給Undo Log提提速,雨露均沾?那我們假設有這個一個Buffer存在于InnoDB,將事務開始前的數據狀態寫入了Undo Log Buffer中,然后開始更新數據。

突然啪一下,很快啊,MySQL由于意外進程退出了,此時會發生一件很尷尬的事情,如果更新的數據一部分已經刷回磁盤了,但是此時事務沒有成功需要回滾,你發現Undo Log隨著進程退出一起沒了,此時就沒有辦法通過Undo Log去做回滾。

那如果剛剛更新完內存,MySQL就掛了呢?此時Redo Log Buffer甚至都可能沒有寫入,即使寫入了也沒有刷到磁盤,Redo Log也丟了。

其實無所謂,因為意外宕機,該事務沒有成功,既然事務事務沒有成功那就需要回滾,而MySQL重啟后會讀取磁盤上的Redo Log文件,將其狀態給加載到Buffer Pool中。而通過磁盤Redo Log文件恢復的狀態和宕機前事務開始前的狀態是一樣的,所以是沒有影響的。然后等待事務commit了之后就會將Redo Log和Binlog刷到磁盤。

流程中仍然存在的問題

你可能認為到這一步就完美了,事實上則不然。假設我們在將Redo Log刷入到磁盤之后MySQL突然宕機了,binlog還沒有來得及寫入。此時重啟,Redo Log所代表的狀態就和Binlog所代表的狀態不一致了。Redo Log恢復到Buffer Pool中的某行的A字段是3,但是任何監聽其Binlog的數據庫讀取出來的數據確是2。

即使Redo Log和Binlog都寫入文件了,但是這個時候MySQL所在的物理機活著VM宕機了,日志仍然會丟失?,F在的OS在你寫入文件的時候,會先將改動的內容寫入的OS Cache中,以此來提高效率。然后根據策略(受你配置的參數的影響)來將OS Cache中的數據刷入磁盤。

基于2PC的一致性保障

從這你可以發現一個關鍵的問題,那就是必須保證Redo Log和Binlog在事務提交時的數據一致性,要么都存在,要么都不存在。MySQL是通過 2PC(two-phase commit protocol)來實現的。

MySQL 崩潰恢復

簡單介紹一下2PC,它是一種保證分布式事務數據一致性的協議,它中文名叫兩階段提交,它將分布式事務的提交拆分成了2個階段,分別是Prepare和Commit/Rollback。

就向兩個拳擊手開始比賽之前,裁判會在中間確認兩個選手的狀態,類似于問你準備好了嗎?得到確認之后,裁判才會說Fight

裁判詢問選手的狀態,對應的是第一階段Prepare;得到了肯定的回答之后,裁判宣布比賽正式開始,對應的是第二階段Commit,但是如果有一方選手沒有準備好,裁判會宣布比賽暫停,此時對應的是第一階段失敗的情況,第二階段的狀態會變為Rollback。裁判就對應2PC中的協調者Coordinator,選手就對應參與者Participant

下面我們通過一張圖來看一下整個流程。

2PC刷入磁盤

Prepare階段,將Redo Log寫入文件,并刷入磁盤,記錄上內部XA事務的ID,同時將Redo Log狀態設置為Prepare。Redo Log寫入成功后,再將Binlog同樣刷入磁盤,記錄XA事務ID。

Commit階段,向磁盤中的Redo Log寫入Commit標識,表示事務提交。然后執行器調用存儲引擎的接口提交事務。這就是整個過程。

驗證2PC機制的可用性

這就是2PC提交Redo Log和Binlog的過程,那在這個期間發生了異常,2PC這套機制真的能保證數據一致性嗎?

假設Redo Log刷入成功了,但是還沒來得及刷入Binlog MySQL就掛了。此時重啟之后會發現Redo Log并沒有Commit標識,此時根據記錄的XA事務找到這個事務,進行回滾。

如果Redo Log刷入成功,而且Binlog也刷入成功了,但是還沒有來的及將Redo Log從Prepare改成Commit MySQL就掛了,此時重啟會發現雖然Redo Log沒有Commit標識,但是通過XID查詢到的Binlog卻已經成功刷入磁盤了。

此時,雖然Redo Log沒有Commit標識,MySQL也要提交這個事務。因為Binlog一旦寫入,就可能會被從庫或者任何消費Binlog的消費者給消費。如果此時MySQL不提交事務,則可能造成數據不一致。而且目前Redo Log和Binlog從數據層面上,其實已經Ready了,只是差個標志位。

好了以上就是本篇博客的全部內容了,歡迎微信搜索關注【SH的全棧筆記】,回復【隊列】獲取MQ學習資料,包含基礎概念解析和RocketMQ詳細的源碼解析,持續更新中。

如果你覺得這篇文章對你有幫助,還麻煩點個贊,關個注,分個享留個言。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容