廢話不多說先來張圖解釋
update T set value = value+1 where ID =2
複製程式碼
我想可能大部分人看完這圖,思考片刻,接下來的就不需要在繼續看了,但是考慮到部分朋友還是新手(包括自己)以及後面複習,還是稍微嘮叨一段。
update過程
首先,上圖中深色背景的表示在執行器中執行,也就是Server層,淺色的是在InnoDB引擎中執行。
由於很多朋友並不是專業的DBA或者對MySQL內部原理並不是特別清晰,所以先對redolog和binlog做簡單的介紹。
-
redolog
重做日誌,屬於物理日誌,上面儲存的是資料庫中最終的內容,有固定的大小,可以迴圈讀寫,一般設定innodb_flush_log_at_trx_commit為1,表示commit事務時將redolog上面的資料刷入到磁碟(具體的可以自行研究redolog file 和redolog buffer)。具有兩個狀態分別是prepare和commit,在MySQL重啟恢復時會根據commit狀態恢復資料。
-
binlog
歸檔日誌,屬於邏輯日誌,上面儲存的是最初的修改邏輯可以簡單的理解為sql語句,可以追加寫,一般設定sync_binlog為1,表示commit事務時將binlog上面的資料刷入到磁碟進行歸檔。資料恢復和同步都是通過binlog來實現的。
下面以文字的方式再次描述一下update T set value = value+1 where ID =2的過程。
- 詞法分析器識別出事update語句;
- 執行器去InnoDB中進行查詢,找到滿足ID = 2 的資料;
- 執行器將value的值加1;
- 執行器讓InnoDB將剛剛的新值寫入到InnoDB的記憶體中;
- InnoDB在redolog中加入一條記錄,並把該記錄的狀態設定為prepare;
- 執行器經“update T set value = value+1 where ID =2” 寫入到binlog中;
- 此時提交事務,將redolog中prepare的的記錄狀態設為commit,並且將記憶體中的新資料刷入磁碟。
以上就是比較簡單的過程理解,那麼為啥要分開寫redolog呢?即傳說中的兩階段提交?這裡再做個簡單的分析。
首先對這種方式的好處做個總結:保證以上所有的過程如果出現MySQL例項奔潰都不會導致事務的丟失或異常。
接下來分析一下這麼做的具體原因:
- 如果是第5步之前crash,就是還沒寫任何日誌,那麼事務就不存在,在恢復後從redolog和binlog中都不會有任何的問題;
- 如果寫完redolog 的prepare出現了crash,那麼恢復時,通過redolog和binlog的對比,會發現只要一個prepare的日誌,那麼會將事務進行回滾,保證redolog和binlog的統一;
- 如果寫完binlog後出現crash,那麼恢復時,會進行根據binlog日誌對redolog進行補償,對redolog之前prepare的記錄修改為commit狀態,事務得到保證;
- 最後commit後crash,redolog和binlog都是正常的。
redolog只出現在InnDB中,而且是迴圈寫的,不能持久儲存,所以暫時不能用redolog來做主從或者資料備份
以上的是總結了很多部落格和書上的內容,並不是完全的原創,自己也是在整理,希望大家能指正不對之處。