簡單分析mysql的InnoDB存儲引擎的磁盤架構


在這裏插入圖片描述

上圖是mysql官方文檔中提供的InnoDB架構圖,左側是內存架構,右側則是磁盤架構。本文主要對磁盤架構簡單分析下。

如上圖右側所示,可以看到InnoDB的磁盤結構由6部分組成:

1.系統表空間(System Tablespace)

默認所有表都會共享的表空間,對應磁盤文件ibdata1。裏面包含四部分:
(1)InnoDB Data Dictionary:數據字典,記錄表和索引的元信息。
(2)Doublewrite Buffer:雙寫緩衝,下邊詳細會說。
(3)change Buffer:寫緩衝區,上文中說過。
(4)undo log:實現mysql事務的原子性,後邊會單獨說。

雙寫緩衝(Doublewrite Buffer)

上篇文章中我們知道了InnoDB每次IO默認爲1頁即16kb,但是操作系統的頁一般是4kb,所以InnoDB的一個頁要寫入到磁盤就要分四次了。
那麼問題來了。
:如果數據寫入到磁盤的時候發生了宕機,而InnoDB只寫入了第一個4kb的時候。那剩下的12kb沒寫進去,這就叫做“部分寫失效”,這就會導致數據丟失。注意redo log日誌進行數據恢復時發現這個頁已經不完成了,所以是恢復不了的。怎麼解決?
:很直觀的答案,保證數據頁的完整性就好了。那怎麼保證。它是這麼做的,在要刷盤之前,也就是redo log應用到磁盤之前,會先拷貝一個副本到doublewrite buffer中。如果出現了部分頁失效,就可以用這個副本還原這個數據頁的內容,然後在恢復數據。這個頁的副本就成爲雙寫緩衝技術,主要靠它來實現數據頁的可靠性完成性
查看Doublewrite Buffer信息的命令:show variables like '%innodb_doublewrite%';,默認就是開啓狀態。
在這裏插入圖片描述

2.獨佔表空間(File-Per-Table Tablespace)

因爲系統的表空間是共享的,爲了防止系統表空間越來越大,纔有的獨佔表空間。該文件爲每個表的表空間提供了一種更靈活的選擇,其中,每個InnoDB表被存儲在其自己的表空間的數據文件(.ibd文件)。也就是有一個表就有一個ibd文件,該文件只存放數據和索引。
show variables like '%innodb_file_per_table%';,可以查看信息,默認就是開啓狀態。
在這裏插入圖片描述

3.通用表空間(General Tablespaces)

也是共享的表空間,跟系統表空間類似。不過它可以自己創建並使用。使用CREATE TABLESPACE語法創建。

4.臨時表空間(Temporary Tablespace)

存儲臨時表的數據,對應文件ibTmp1。在正常關閉或初始化中止時,將刪除臨時表空間,並在每次啓動服務器時重新創建

5.重做日誌(redo log)

提供崩潰恢復。上一篇文章中說過。

6.撤銷表空間(undo Tablespaces)

也就是undo log,默認配置中,是放在系統表空間的,也可以獨立出來。
redo log + undo log合起來就是mysql的事務日誌,redo log 實現持久性,undo log實現原子性。
查看undo log信息的命令:show global variables like '%undo%';
在這裏插入圖片描述

undo log

undo log又叫回滾日誌,記錄了我們事務發生前的一個狀態,比如,我們在修改的時候發生了異常,就可以用undo log 來實現回滾的操作。
有了redo log 和undo log後,那麼一條更新語句的執行流程爲:
(1)從內存或磁盤讀取到這條數據,返回給server層
(2)執行器把這條數據修改
(3)記錄undo log
(4)記錄redo log並將這條數據狀態設爲 prepare
(5)調用存儲引擎的api,在buffer pool修改數據
???????????(總感覺這裏少點啥)??????????????
(6)事務提交將redo log中這條數據的狀態改爲commit,再由後臺線程刷到磁盤
那麼問題來了。
:如上述流程中,如果事務正在提交的時候mysql掛了咋辦?

這就引出了新的東西 binary log

binary log

又稱 binlog,二進制日誌。主要記錄了我們所有的DDL(創建表庫和刪除表庫的操作)、DML(增刪改的操作)語句。
作用:
(1)數據恢復,可以將binlog日誌解析出來,應用到全量備份中。必須依賴全量備份,不然很難恢復
(2)主從複製,主從之間數據如何保持同步的?就是基於binlog去實現的。
上個問題的解答:有了binlog,那麼在commit之前先將更新語句寫入到binlog中。就算在提交事務的時候mysql崩潰重啓了,那也會以binlog爲準,將語句在執行commit一次就行了。所以只要寫入到binlog後,就意味着語句執行成功了。

一條更新語句的完成執行流程圖

在這裏插入圖片描述
<<上一篇:InnoDB存儲引擎的內存架構

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