MySQL日誌15連問

前言

大家好,我是撿田螺的小男孩。金九銀十已經來了,整理了15道經典MySQL日誌面試題,希望對大家有幫助。

  • 公衆號: 撿田螺的小男孩

1. redo log是什麼? 爲什麼需要redo log?

redo log 是什麼呢?

  • redo log 是重做日誌
  • 它記錄了數據頁上的改動。
  • 它指事務中修改了的數據,將會備份存儲。
  • 發生數據庫服務器宕機、或者髒頁未寫入磁盤,可以通過redo log恢復。
  • 它是Innodb存儲引擎獨有的

爲什麼需要 redo log?

  • redo log主要用於MySQL異常重啓後的一種數據恢復手段,確保了數據的一致性。
  • 其實是爲了配合MySQL的WAL機制。因爲MySQL進行更新操作,爲了能夠快速響應,所以採用了異步寫回磁盤的技術,寫入內存後就返回。但是這樣,會存在crash後內存數據丟失的隱患,而redo log具備crash safe的能力。

2. 什麼是WAL技術, 好處是什麼.

  • WAL,中文全稱是Write-Ahead Logging,它的關鍵點就是日誌先寫內存,再寫磁盤。MySQL執行更新操作後,在真正把數據寫入到磁盤前,先記錄日誌
  • 好處是不用每一次操作都實時把數據寫盤,就算crash後也可以通過redo log恢復,所以能夠實現快速響應SQL語句。

3. redo log的寫入方式

redo log包括兩部分內容,分別是內存中的日誌緩衝(redo log buffer)和磁盤上的日誌文件(redo log file)。

mysql每執行一條DML語句,會先把記錄寫入redo log buffer ,後續某個時間點再一次性將多個操作記錄寫到redo log file 。這種先寫日誌,再寫磁盤的技術,就是WAL

在計算機操作系統中,用戶空間(user space)下的緩衝區數據,一般是無法直接寫入磁盤的,必須經過操作系統內核空間緩衝區(即OS Buffer)。

  • 日誌最開始會寫入位於存儲引擎Innodb的redo log buffer,這個是在用戶空間完成的。
  • 然後再將日誌保存到操作系統內核空間的緩衝區(OS buffer)中。
  • 最後,通過系統調用fsync(),從OS buffer寫入到磁盤上的redo log file中,完成寫入操作。這個寫入磁盤的操作,就叫做刷盤

我們可以發現,redo log buffer寫入到redo log file,是經過OS buffer中轉的。其實可以通過參數innodb_flush_log_at_trx_commit進行配置,參數值含義如下:

  • 0:稱爲延遲寫,事務提交時不會將redo log buffer中日誌寫入到OS buffer,而是每秒寫入OS buffer並調用寫入到redo log file中。
  • 1:稱爲實時寫,實時刷”,事務每次提交都會將redo log buffer中的日誌寫入OS buffer並保存到redo log file中。
  • 2: 稱爲實時寫,延遲刷。每次事務提交寫入到OS buffer,然後是每秒將日誌寫入到redo log file。

4. Redo log的執行流程

我們來看下Redo log的執行流程,假設執行的SQL如下:

update T set a =1 where id =666
複製代碼

Redo log的執行流程

  1. MySQL客戶端將請求語句update T set a =1 where id =666,發往MySQL Server層。
  2. MySQL Server 層接收到SQL請求後,對其進行分析、優化、執行等處理工作,將生成的SQL執行計劃發到InnoDb存儲引擎層執行。
  3. InnoDb存儲引擎層將a修改爲1的這個操作記錄到內存中。
  4. 記錄到內存以後會修改redo log 的記錄,會在添加一行記錄,其內容是需要在哪個數據頁上做什麼修改
  5. 此後,將事務的狀態設置爲prepare ,說明已經準備好提交事務了。
  6. 等到MySQL Server層處理完事務以後,會將事務的狀態設置爲commit,也就是提交該事務。
  7. 在收到事務提交的請求以後,redo log會把剛纔寫入內存中的操作記錄寫入到磁盤中,從而完成整個日誌的記錄過程。

5. redo log 爲什麼可以保證crash safe機制呢?

  • 因爲redo log每次更新操作完成後,就一定會寫入的,如果寫入失敗,說明此次操作失敗,事務也不可能提交。
  • redo log內部結構是基於頁的,記錄了這個頁的字段值變化,只要crash後讀取redo log進行重放,就可以恢復數據。

6. binlog的概念是什麼, 起到什麼作用, 可以保證crash-safe嗎?

  • bin log是歸檔日誌,屬於MySQL Server層的日誌。可以實現主從複製數據恢復兩個作用。
  • 當需要恢復數據時,可以取出某個時間範圍內的bin log進行重放恢復。
  • 但是bin log不可以做crash safe,因爲crash之前,bin log可能沒有寫入完全MySQL就掛了。所以需要配合redo log纔可以進行crash safe。

7. binlog和redolog的不同點有哪些?

8. 執行器和innoDB在執行update語句時候的流程是什麼樣的?

  • 執行器在優化器選擇了索引後,會調用InnoDB讀接口,讀取要更新的行到內存中
  • 執行SQL操作後,更新到內存,然後寫redo log,寫bin log,此時即爲完成。
  • 後續InnoDB會在合適的時候把此次操作的結果寫回到磁盤。

9. 如果數據庫誤操作, 如何執行數據恢復?

數據庫在某個時候誤操作,就可以找到距離誤操作最近的時間節點的bin log,重放到臨時數據庫裏,然後選擇誤刪的數據節點,恢復到線上數據庫。

10. binlog日誌三種格式

binlog日誌有三種格式

  • Statement:基於SQL語句的複製((statement-based replication,SBR))
  • Row:基於行的複製。(row-based replication,RBR)
  • Mixed:混合模式複製。(mixed-based replication,MBR)

Statement格式

每一條會修改數據的sql都會記錄在binlog中

  • 優點:不需要記錄每一行的變化,減少了binlog日誌量,節約了IO,提高性能。
  • 缺點:由於記錄的只是執行語句,爲了這些語句能在備庫上正確運行,還必須記錄每條語句在執行的時候的一些相關信息,以保證所有語句能在備庫得到和在主庫端執行時候相同的結果。

Row格式

不記錄sql語句上下文相關信息,僅保存哪條記錄被修改。

  • 優點:binlog中可以不記錄執行的sql語句的上下文相關的信息,僅需要記錄那一條記錄被修改成什麼了。所以rowlevel的日誌內容會非常清楚的記錄下每一行數據修改的細節。不會出現某些特定情況下的存儲過程、或function、或trigger的調用和觸發無法被正確複製的問題。
  • 缺點:可能會產生大量的日誌內容。

Mixed格式

實際上就是Statement與Row的結合。一般的語句修改使用statment格式保存binlog,如一些函數,statement無法完成主從複製的操作,則採用row格式保存binlog,MySQL會根據執行的每一條具體的sql語句來區分對待記錄的日誌形式

11. 什麼是MySQL兩階段提交, 爲什麼需要兩階段提交?

其實所謂的兩階段就是把一個事務分成兩個階段來提交。

兩階段提交

兩階段提交主要有三步曲:

  1. redo log在寫入後,進入prepare狀態
  2. 執行器寫入bin log
  3. 進入commit狀態,事務可以提交。

爲什麼需要兩階段提交呢?

  • 如果不用兩階段提交的話,可能會出現這樣情況:bin log寫入之前,機器crash導致需要重啓。重啓後redo log繼續重放crash之前的操作,而當bin log後續需要作爲備份恢復時,會出現數據不一致的情況。
  • 如果是bin log commit之前crash,那麼重啓後,發現redo log是prepare狀態且bin log完整(bin log寫入成功後,redo log會有bin log的標記),就會自動commit,讓存儲引擎提交事務。
  • 兩階段提交就是爲了保證redo log和binlog數據的安全一致性。只有在這兩個日誌文件邏輯上高度一致了。你才能放心的使用redo log幫你將數據庫中的狀態恢復成crash之前的狀態,使用binlog實現數據備份、恢復、以及主從複製。

12. 如果不是兩階段提交, 先寫redo log和先寫bin log兩種情況各會遇到什麼問題?

  • 先寫redo log,crash後bin log備份恢復時少了一次更新,與當前數據不一致。
  • 先寫bin log,crash後,由於redo log沒寫入,事務無效,所以後續bin log備份恢復時,數據不一致。

13. binlog刷盤機制

所有未提交的事務產生的binlog,都會被先記錄到binlog的緩存中。等該事務提交時,再將緩存中的數據寫入binlog日誌文件中。緩存的大小由參數binlog_chache_size控制。

binlog什麼時候刷新到磁盤呢?由參數sync_binlog控制

  • sync_binlog爲0時,表示MySQL不控制binlog的刷新,而是由系統自行判斷何時寫入磁盤。選這種策略,一旦操作系統宕機,緩存中的binlog就會丟失。
  • sync_binlog爲N時,每N個事務,纔會將binlog寫入磁盤。。
  • sync_binlog爲1時,則表示每次commit,都將binlog 寫入磁盤。

來看一個比較完整的流程圖吧:

14.undo log 是什麼?它有什麼用

  • undo log 叫做回滾日誌,用於記錄數據被修改前的信息。
  • 它跟redo log重做日誌所記錄的相反,重做日誌記錄數據被修改後的信息。undo log主要記錄的是數據的邏輯變化,爲了在發生錯誤時回滾之前的操作,需要將之前的操作都記錄下來,這樣發生錯誤時纔可以回滾。

15. 說說Redo log的記錄方式

redo log的大小是固定。它採用循環寫的方式記錄,當寫到結尾時,會回到開頭循環寫日誌。如下圖(圖片來源網絡):

redo log 循環寫入

redo log buffer(內存中)是由首尾相連的四個文件組成的,它們分別是:ib_logfile_1、ib_logfile_2、ib_logfile_3、ib_logfile_4。

  • write pos表示當前寫入記錄位置(寫入磁盤的數據頁的邏輯序列位置)
  • check point表示刷盤(寫入磁盤)後對應的位置。
  • write pos到check point之間的部分用來記錄新日誌,也就是留給新記錄的空間。
  • check point到write pos之間是待刷盤的記錄,如果不刷盤會被新記錄覆蓋。

有了 redo log,當數據庫發生宕機重啓後,可通過 redo log將未落盤的數據(check point之後的數據)恢復,保證已經提交的事務記錄不會丟失,這種能力稱爲crash-safe

參考與感謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章