redo log與binlog間的破事
前言
今天就來聊聊InnoDB是如何保證redo log與binlog兩份日志之間的邏輯一致。
兩階段提交
redo log(重做日志)讓InnoDB存儲引擎擁有了崩潰恢復能力。
binlog(歸檔日志)保證了MySQL集群架構的數(shù)據(jù)一致性。
雖然它們都屬于持久化的保證,但是則重點不同。
在執(zhí)行更新語句過程,會記錄redo log與binlog兩塊日志,以基本的事務為單位,redo log在事務執(zhí)行過程中可以不斷寫入,而binlog只有在提交事務時才寫入,所以redo log與binlog的寫入時機不一樣。

回到正題,redo log與binlog兩份日志之間的邏輯不一致,會出現(xiàn)什么問題?
我們以update語句為例,假設id=2的記錄,字段c值是0,把字段c值更新成1,SQL語句為update T set c=1 where id=2。
假設執(zhí)行過程中寫完redo log日志后,binlog日志寫期間發(fā)生了異常,會出現(xiàn)什么情況呢?

由于binlog沒寫完就異常,這時候binlog里面沒有對應的修改記錄。因此,之后用binlog日志恢復數(shù)據(jù)時,就會少這一次更新,恢復出來的這一行c值是0,而原庫因為redo log日志恢復,這一行c值是1,最終數(shù)據(jù)不一致。

為了解決兩份日志之間的邏輯一致問題,InnoDB存儲引擎使用兩階段提交方案。
原理很簡單,將redo log的寫入拆成了兩個步驟prepare和commit,這就是兩階段提交。

使用兩階段提交后,寫入binlog時發(fā)生異常也不會有影響,因為MySQL根據(jù)redo log日志恢復數(shù)據(jù)時,發(fā)現(xiàn)redo log還處于prepare階段,并且沒有對應binlog日志,就會回滾該事務。

再看一個場景,redo log設置commit階段發(fā)生異常,那會不會回滾事務呢?

并不會回滾事務,它會執(zhí)行上圖框住的邏輯,雖然redo log是處于prepare階段,但是能通過事務id找到對應的binlog日志,所以MySQL認為是完整的,就會提交事務恢復數(shù)據(jù)。
站在巨人的肩膀上
《MySQL實戰(zhàn)45講》 《從零開始帶你成為MySQL實戰(zhàn)優(yōu)化高手》 《MySQL技術Innodb存儲引擎》
1. 面試官:Spring AOP、AspectJ、CGLIB 都是什么鬼?它們有什么關系?
最近面試BAT,整理一份面試資料《Java面試BATJ通關手冊》,覆蓋了Java核心技術、JVM、Java并發(fā)、SSM、微服務、數(shù)據(jù)庫、數(shù)據(jù)結構等等。
獲取方式:點“在看”,關注公眾號并回復 Java 領取,更多內容陸續(xù)奉上。
文章有幫助的話,在看,轉發(fā)吧。
謝謝支持喲 (*^__^*)

