完全掌握MySQL原理篇之InnoDB儲存引擎架構設計

2022-01-19 19:00:26
本篇文章給大家帶來了關於mysql原理中InnoDB儲存引擎架構設計的相關知識,希望對大家有幫助。

InnoDB元件結構:

  1. buffer pool : 緩衝池,快取磁碟的資料

  2. redo log buffer :記錄對緩衝池的操作,根據策略寫入磁碟防止宕機但事務已經提交而丟失資料

  3. undo log :當對緩衝池的資料進行修改時,在事務未提交的時候都可以進行回滾,將舊值寫入 undo 紀錄檔檔案便於回滾,此時緩衝池的資料與磁碟中的不一致,是髒資料

1. Buffer Pool

假設現在有一條更新語句:

update users set name = 'lisi' where id = 1

需要更新到資料庫,InnoDB會執行哪些操作呢?

圖片

首先,InnoDB會判讀緩衝池裡是否存在 id = 1 這條資料,如果不存在則從磁碟中載入到緩衝池中,而且還會對這行資料加獨佔鎖,防止多個sql同時修改這行資料。

圖片

2. undo 紀錄檔檔案

假設 id = 1 這條資料name原來的值 name = 'zhangsan',現在我們要更新為 name = 'lisi' , 那麼我們就需要把舊值name='zhangsan'和id=1這些資訊寫入到undo紀錄檔檔案中。

對於熟悉資料庫的同學來說都瞭解事務的概念,在事務未提交之前,所有操作都有可能進行回滾,即可以把 name = 'lisi' 回滾到 name = 'zhangsan',所以將更新前的值寫到undo紀錄檔檔案。

圖片

3. 更新buffer pool 資料

在undo紀錄檔檔案寫入完畢之後,便開始更新記憶體中的這條資料。把 id = 1 的 name = 'zhangsan' 更新為 name = 'lisi'。這時記憶體中的資料已經更新完畢,但磁碟上的還沒有變化,此時出現了不一致的髒資料。

圖片

這時可能有一個疑問,萬一事務提交完成,但MySQL服務宕機了,而記憶體中的資料還沒寫入到磁碟,是不是會造成資料丟失而造成sql執行資料前後不一致?

4. redo log buffer

在InnoDB結構中,有一個 redo log buffer 緩衝區存放redo紀錄檔,所謂redo紀錄檔,例如 把id=1,name='zhangsan'修改為name='lisi' 便是一條紀錄檔。

圖片

但這時redo log buffer 還僅僅存在記憶體中,沒能實現MySQL宕機後的資料恢復。

5. 事務沒提交,資料庫宕機後有影響嗎?

其實並沒有影響,事務沒有提交,意味著執行沒有成功,就算MySQL崩潰或者宕機後,記憶體中的 buffer pool 和 redo log buffer 修改過的資料都會丟失,也並不影響資料前後的一致性。如果事務提交失敗,那資料庫的資料更加不會改變。

圖片

6. 提交事務,redo紀錄檔的設定策略

在提交事務時,redo日記會根據策略實現把redo紀錄檔從 redo log buffer 裡寫入磁碟。策略通過 innoDB_flush_log_at_trx_commit 來設定。

  1. innoDB_flush_log_at_trx_commit的引數為0,就算事務提交後,也不會把redo紀錄檔寫入磁碟。MySQL宕機後會記憶體中的資料會丟失。

圖片

  1. innoDB_flush_log_at_trx_commit的引數為1,事務提交後,redo紀錄檔會從記憶體刷入磁碟,只要事務提交成功,redo log 就必然存在磁碟裡。

圖片

此時就算buffer pool 的資料沒有刷進磁碟,也可以從redo log 中得知修改過哪些資料,MySQL宕機重新啟動後,可以從redo紀錄檔中恢復修改的資料。

圖片

  1. innoDB_flush_log_at_trx_commit的引數為2,事務提交後,redo log 僅僅停留在 os cache 中,還沒刷進磁碟,萬一此時服務宕機了。那麼os cache 中的資料也會丟失,即使事務提交成功,也會造成資料丟失。

圖片

看完這幾種相信為了保證資料安全,引數為1是最佳策略。

7. 事務的最終提交,binlog

binlog其實是屬於MySQL Server 的紀錄檔檔案,而在這出提出是因為與redo log有著很大的關聯。

1) biglog 與 redo log的區別

  • redo log:記錄的是偏物理性質重做紀錄檔,比如 「對哪個資料頁中的什麼記錄,做了哪些修改」

  • binlog:偏向於邏輯性的紀錄檔,如:「對users表中的id=10的一行資料做了更新操作,更新以後的值是什麼」

2) 提交事務的時候同時寫入binlog

在執行更新的同時,innoDB與執行器一直在互動,包括載入資料到緩衝池,寫入undo紀錄檔檔案,更新記憶體資料,寫redo紀錄檔和刷入磁碟等。而對binlog的寫入也是由執行器執行。

圖片

其中 1、2、3、4步驟為執行更新語句做的事,而 5、6是提交事務開始做的事。

3) binlog紀錄檔刷盤策略分析

sync_binlog引數控制binlog的刷盤策略

  1. sync_ binlog預設值是0,提交事務後,會把binlog紀錄檔存在 os cache 中,MySQL宕機後會造成os cache中資料的丟失

  2. sync_binlog 值為1,提交事務後,把binlog紀錄檔直接刷入磁碟中。

4) 基於binlog 和 redo log 完成事務的提交

binlog寫入磁碟後,會把binlog紀錄檔檔案所在的位置和檔名稱都寫入redo log紀錄檔檔案中,同時在redo log紀錄檔檔案裡寫入一個commit標記。

圖片

5) commit 標記有什麼意義?

commit 標記意義著保持redo log 和 binlog 紀錄檔一致。如果在步驟5或者步驟6,事務提交開始,MySQL宕機了,redo log 中並沒有commit標記,都算事務提交失敗。

意味著 commint 標記是事務最終提交成功。

8. buffer pool 髒資料刷入磁碟

髒資料刷入磁碟是由後臺IO執行緒隨機刷入磁碟的。

圖片

這時候考慮到,在刷入磁碟之前,MySQL宕機怎麼辦?這時候,事務已經提交成功,redo log 中也有commit標記,就算宕機了,重新啟動後,也會根據redo紀錄檔檔案把資料更新到記憶體中,等待IO執行緒的刷盤。

9. 總結

通過更新語句執行分析之後,瞭解到InnoDB儲存引擎中包含了 buffer pool 緩衝池、redo log buffer 緩衝區等快取資料,undo、reod log等紀錄檔檔案,同時也有MySQL Server 的紀錄檔檔案。

在執行更新語句的時候,會修改buffer pool、寫undo紀錄檔檔案、 寫redo log buffer等操作;提交事務時,會將redo log 刷盤,binlog刷盤,寫入binlog檔名稱和位置,寫入commit標記,最後等待IO執行緒將buffer pool的髒資料隨機刷盤。

推薦學習:

以上就是完全掌握MySQL原理篇之InnoDB儲存引擎架構設計的詳細內容,更多請關注TW511.COM其它相關文章!