天天看點

【MySQL】MySQL日志系統以及InnoDB背後的技術

一、Redo Log

在MySQL存儲引擎的底部是實體存儲層,它是檔案的實體存儲層(包括二進制日志、資料檔案、錯誤日志、慢查詢日志、完整日志、redo/undo 日志等)。

1、什麼是redo log

在MySQL中,如果每次更新操作都需要寫入磁盤,那麼磁盤也必須找到相應的記錄,然後進行更新。整個過程的 IO 成本和搜尋成本都很高。

為了解決這個問題,MySQL中經常提到的WAL技術,WAL的全稱是Write Ahead Logging(提前寫入日志)。它的關鍵點是首先寫入日志,然後寫入磁盤

具體來說,當需要更新記錄時,InnoDB引擎将首先将記錄寫入重做日志并更新記憶體。此時,更新完成。同時,InnoDB引擎會在适當的時候将此操作記錄更新到磁盤,此更新通常在系統空閑時完成。

2、redo log工作原了解析

Redo log 是一個循環重用的檔案集,負責記錄 InnoDB 存儲引擎中緩沖池(Buffer Pool)的所有實體修改日志。

送出事務時,日志緩沖區 log buffer 将重新整理為 Redo log 日志檔案。

當檢查點位置的 LSN 和最新寫入的 LSN 內插補點(checkpoint_age)達到總 Redo log 日志空間的 75% 時,InnoDB 存儲引擎将執行異步重新整理操作,直到其降至75%以下,并釋放重做日志空間。

當 checkpoint_age  達到總檔案大小的 90% 時,将觸發同步重新整理。此時,InnoDB處于暫停狀态,無法運作。

【MySQL】MySQL日志系統以及InnoDB背後的技術

write pos 寫入位置是目前記錄的位置。它在書寫時向後移動。寫入3号檔案的末尾後,将傳回0号檔案的開頭。checkpoint 檢查點是要擦除的目前位置。它也向後移動并循環。在擦除記錄之前,應将記錄更新為資料檔案。

write pos 寫入位置和 checkpoint 檢查點之間是的空白部分,可以用來記錄新的操作。如果寫入pos 趕上了檢查點 checkpoint,則意味着 Redo log 已滿,此時無法執行新的更新。相反,停止并擦除一些記錄以推進 checkpoint 。

通過 Redo log 日志,InnoDB可以確定即使資料庫異常重新開機,之前送出的記錄也不會丢失。這種能力稱為 crash-safe (碰撞安全)。

3、redo log 如何設定

Redo log 日志的大小直接影響資料庫的處理能力,如果設定太小,強制檢查點 checkpoint  操作将頻繁重新整理髒頁。

InnoDB 的 Redo log 是固定大小的,比如可以配置為一組 4 個檔案,每個檔案的大小是 1GB,總共就可以記錄 4GB 的操作,從頭開始寫,寫到末尾就又回到開頭循環寫。

最後我們需要将重做日志設定為更大的大小。在5.6版之前,Redo log 日志的總大小不能超過3.8GB。5.7版之後,此限制被釋放。由于它太小而無法影響性能,是以将其設定為盡可能大是否更好?

二、Bin Log

MySQL有兩個部分:一個是引擎層,負責與存儲相關的具體事宜。我們上面讨論的 Redo log 日志是 InnoDB引擎的一個獨特日志,

一個是伺服器層,它主要在MySQL伺服器層做事情,伺服器層日志,稱為 Bin Log(歸檔日志) 。

MySQL期初沒有 InnoDB 存儲引擎。MySQL自己的引擎是 MyISAM,但 MyISAM 沒有崩潰安全功能,Bin log 日志隻能用于存檔。

三、InnoDB執行與Log系統的關系

執行此更新語句時,執行器和InnoDB引擎的内部工作原理:

【MySQL】MySQL日志系統以及InnoDB背後的技術

一、執行器首先查找引擎以獲得行。ID是主鍵,引擎直接使用樹搜尋來查找該行。

如果該行的資料頁已經在記憶體中,它将直接傳回到執行器;否則,您需要在傳回之前從磁盤讀取記憶體。

二、執行器擷取引擎給出的行資料,将1加到該值上,擷取一行新資料,然後調用引擎接口寫入新資料行。

三、引擎将新資料更新到記憶體,并将更新操作記錄在重做日志中。此時,重做日志處于準備狀态。然後告訴執行者執行已完成,事務可以随時送出。

四、執行器為該操作生成 Bin Log,并将 Bin Log 歸檔日志寫入磁盤。

五、MySQL 執行器調用引擎的送出事務接口,引擎将剛剛寫入的  Redo Log  日志更改為送出狀态,更新完成。

2、兩階段送出

流程圖中可以看到,MySQL InnoDB 将 Redo log 的寫入拆成了兩個步驟:prepare 和 commit,這就是"兩階段送出"。

Redo log 和 Bin Log 都可以用來訓示事務的送出狀态。兩階段送出是為了保持兩種狀态的邏輯一緻。

四、 Redo log 與 Bin Log 差別

Redo log 重做日志對于InnoDB引擎是唯一的;Binlog 歸檔位置是在MySQL的伺服器層上實作的,可以被所有引擎使用。

Redo log 是一個實體日志,記錄對資料頁所做的更改;Bin log是記錄語句原始邏輯的邏輯日志。

Redo log 是循環寫入的,空間會用完;可以附加 Bin log,Bin log 檔案在寫入到一定大小後将切換到下一個,并且不會覆寫上一個日志。

五、Undo Log

1、什麼是 Undo Log

實體層在邏輯上分為系統表空間、使用者表空間和 Undi Log 日志。

系統表空間包含 ibdata 檔案和一些 Undo檔案。ibdata檔案包含 insert buffer 插入緩沖區段、 double write 雙寫段、復原段、索引段、資料字典段和 Undo 資訊段。

MySQL 5.7的新特性如下:Undo 撤銷與共享表空間的 ibdata 檔案分離。您可以在安裝MySQL時自行指定檔案大小和編号。

MySQL 8.0的新特性如下:InnoDB表的資料字典和 Undo 與共享表空間 ibdata 完全分離。此前,ibdata 檔案中的資料字典需要與獨立表空間ibd檔案中的資料庫字典保持一緻。

2、Write Ahead Logging(WAL)

首先寫入日志,然後寫入磁盤。成功寫入日志後,事務不會丢失。

稍後,檢查點機制将確定磁盤實體檔案和重做日志之間的一緻性;

使用 Redo Log 記錄更改的資料,即使用 Redo Log 來記錄交易資料的更改值;

使用 Undo Log 記錄更改前的資料,也就是說,Undo Log 将記錄事務資料更改前的值,以便復原和多版本讀取其他事務。

六、事務的四大特性與Log系統的關系

事務的 ACID 都需要通過 Redo、Undo 日志來保證等。

原子性: 原子性與 WAL 有很大的關系。需要從 Redo 重做日志恢複的資料。如果事務沒有送出,緩沖池的髒頁被重新整理,那麼不應該存在的資料怎麼會消失?它需要通過撤銷來實作,這是通過 Undo 重做來保證的。是以,最終原子性由 Redo 的 WAL 機制保證。

持久性: 一旦事務通過原子性送出,即使在停機的情況下,也可以從邏輯上檢索資料,然後再次寫入實體存儲空間。這確定了資料不會從邏輯和實體方面(即資料庫的持久性)丢失。

隔離性: 指事務的執行不能受到其他事務的幹擾,即事務中使用的操作和資料與其他并發事務隔離。鎖定和多版本控制符合隔離。MVCC多版本實作有三個隐藏字段。復原指針(DB_ROLL_PT)指向目前記錄項的 Rollback Segment 的 Undo log日志記錄,通過該記錄可以找到以前版本的資料。

總結