02 | 日誌系統:一條SQL更新語句是如何執行的?

taotaoo發表於2019-03-27

與查詢流程不一樣的是,更新流程還涉及兩個重要的日誌模組,它們正是我們今天要討論的主角:redo log(重做日誌)和 binlog(歸檔日誌)

重要的日誌模組:redo log

如果每一次的更新操作都需要寫進磁碟,然後磁碟也要找到對應的那條記錄,然後再更新,整個過程 IO 成本、查詢成本都很高。為了解決這個問題,MySQL 的設計者就用了類似酒店掌櫃粉板的思路來提升更新效率。

而粉板和賬本配合的整個過程,其實就是 MySQL 裡經常說到的 WAL 技術,WAL 的全稱是 Write-Ahead Logging,它的關鍵點就是先寫日誌,再寫磁碟,也就是先寫粉板,等不忙的時候再寫賬本。

具體來說,當有一條記錄需要更新的時候,InnoDB 引擎就會先把記錄寫到 redo log(按我理解這個其實還是要寫檔案,只不過是順序寫,效率高)裡面,並更新記憶體,這個時候更新就算完成了。同時,InnoDB 引擎會在適當的時候,將這個操作記錄更新到磁碟裡面,而這個更新往往是在系統比較空閒的時候做。

InnoDB 的 redo log 是固定大小的,比如可以配置為一組 4 個檔案,每個檔案的大小是 1GB,那麼這塊“粉板”總共就可以記錄 4GB 的操作。從頭開始寫,寫到末尾就又回到開頭迴圈寫,如下面這個圖所示。

img

這種機制保證了即使資料庫異常當機,之前的資料也不會丟失,這個能力成為crash-safe

補充

作用

  • 確保事務的永續性,防止在發生故障的時間點,尚有髒頁未寫入磁碟,在重啟mysql服務的時候,根據redo log進行重做,從而達到事務的永續性這一特性。
    • 這個事情我是這樣想的,redolog本身是為了彌補binlog的固有的缺點才做的。binlog不會實時寫磁碟,特別是在事務的情況下,不commit binlog不會寫入磁碟。
    • redolog是實時順序寫磁碟的(當然也不是實時,但是最遲1s寫入)

內容

  • 物理格式的日誌,記錄的是物理資料頁面的修改的資訊。對比binlog的格式是具體的sql操作語句。

什麼時候產生

  • 事務或者操作開始的時候就會產生

是麼時候釋放

  • 當對應事務或操作的髒頁寫入到磁碟之後,redo log的使命也就完成了,重做日誌佔用的空間就可以重用(被覆蓋)。

重要的日誌模組:binlog

redo log是innodb引擎特有的日誌,而引擎層上面的server層(如果忘了mysql的架構,記得看上一篇的圖示)也有自己的日誌,成為binlog(歸檔日誌)。

  • 為啥會有兩份日誌嘛?

    因為最開始 MySQL 裡並沒有 InnoDB 引擎。MySQL 自帶的引擎是 MyISAM,但是 MyISAM 沒有 crash-safe 的能力,binlog 日誌只能用於歸檔。而 InnoDB 是另一個公司以外掛形式引入 MySQL 的,既然只依靠 binlog 是沒有 crash-safe 能力的,所以 InnoDB 使用另外一套日誌系統——也就是 redo log 來實現 crash-safe 能力。

補充

作用

  • 用於複製,在主從複製中,從庫利用主庫上的binlog進行重播,實現主從同步。
  • 用於資料庫的基於時間點的還原。(在異常重啟的情況下,會用到redolog

內容

  • 簡單認為就是執行過的sql語句(查詢啥的就不需要了)

什麼時候產生

  • 事務提交的時候,一次性將事務中的sql語句(一個事物可能對應多個sql語句)按照一定的格式記錄到binlog中。

什麼時候釋放

  • binlog的預設是保持時間由引數expire_logs_days配置,也就是說對於非活動的日誌檔案,在生成時間超過expire_logs_days配置的天數之後,會被自動刪除。

redolog和binlog的不同

  • 作用不同:redo log是保證事務的永續性的,是事務層面的,binlog作為還原的功能,是資料庫層面的(當然也可以精確到事務層面的),雖然都有還原的意思,但是其保護資料的層次是不一樣的。
  • 內容不同:redo log是物理日誌,是資料頁面的修改之後的物理記錄,binlog是邏輯日誌,可以簡單認為記錄的就是sql語句
  • 另外,兩者日誌產生的時間,可以釋放的時間,在可釋放的情況下清理機制,都是完全不同的。
  • 恢復資料時候的效率,基於物理日誌的redo log恢復資料的效率要高於語句邏輯日誌的binlog

update的流程

img

這裡面涉及到了兩階段提交。 MySQL通過兩階段提交過程來完成事務的一致性的,也即redo log和binlog的一致性的,理論上是先寫redo log,再寫binlog,兩個日誌都提交成功(刷入磁碟),事務才算真正的完成。

如何讓資料庫恢復到半個月內的任何一秒的狀態?

如果你的 DBA 承諾說半個月內可以恢復,那麼備份系統中一定會儲存最近半個月的所有 binlog,同時系統會定期做整庫備份。這裡的“定期”取決於系統的重要性,可以是一天一備,也可以是一週一備。

當需要恢復到指定的某一秒時,比如某天下午兩點發現中午十二點有一次誤刪表,需要找回資料,那你可以這麼做:

  • 首先,找到最近的一次全量備份,如果你運氣好,可能就是昨天晚上的一個備份,從這個備份恢復到臨時庫;
  • 然後,從備份的時間點開始,將備份的 binlog 依次取出來,重放到中午誤刪表之前的那個時刻。

相關文章