天天看點

InnoDB體系結構之存儲篇

Innodb存儲引擎在存儲設計上模仿了Oracle的存儲結構,其資料是按照表空間進行管理的。所有的資料都要存儲在表空間中。

Innodb的表空間分為:

  • 系統表空間

建立一個資料庫時,Innodb會初始化一個名為ibdata1的系統表空間。可通過innodb_data_file_path來定義其路徑、大小以及自動

擴充政策。例如 innodb_data_file_path= ibdata1:1G:autoextend。

系統表空間中主要包括:資料字典、double write buffer、change buffer、復原段(undo頁的索引資訊)、undo表空間(5.6之後

可單獨定義其路徑)、使用者資料(如果innodb_file_per_table=0)等。

  • 獨立表空間

可通過innodb_file_per_table=1來讓每張表有獨立的表空間,每張表有各自的xx.ibd檔案,但是表定義資訊還是在ibdata1中。這

裡面主要存儲資料資訊(聚集索引)和普通索引。

  • Undo表空間

5.6開始支援建立獨立的undo表空間

  • 臨時表空間

5.7引入的獨立表空間檔案ibtmp1。預設值12M。由innodb_tmp_data_file_path定義。通用臨時表create temeprry table和SQL執

行過程中産生的内部臨時表(using temperory table)會公用這個臨時表空間檔案。執行個體啟動時建立,關閉時會被删除。5.7中

internal_tmp_disk_storage_engine=Innodb,8.0中internal_tmp_mem_storage_engine=Temptable

  • 通用表空間

5.7引入general tablespace,給8.0做鋪墊。但是到了8.0,廢棄了MyIsam存儲引擎之後之後,一些系統表就放到通用表空間裡。

從上面我們已經知道,Innodb的資料存儲脫離不了表空間的管理。那麼我們從單個表空間檔案入手,前面已經知道單個表空間就

是由單個或者多個B+樹索引來構成,下面看一下表空間具體的構成:

段(Segment)

既然表空間由B+樹構成,那麼建立一顆B+樹就需要葉子段和内節點段來組成。段是一個邏輯概念,來用來管理實體檔案,是構

成索引、表、復原段的基本元素

簇(Extent)

上面已經知道段是一個邏輯概念,那麼實體上簇就是構成段的基本元素。簇由實體上一段連續配置設定的空間構成。一個段由1個或

者若幹個簇組成。預設1個簇由連續的64個page組成,因為一個page的預設值大小為16K,是以一個簇的預設值就是1M.但是這

個大小我們可以設定為1M/2M/4M,由于page也可以更改,是以要通過這兩個來決定有多少個page來組成一個簇。每個簇之間的

實體順序是不連續的。

頁(Page)

Innodb最小的I/O機關。預設值16K。5.6可以調整為4k、8k。5.7可以調整為16K、32K。頁包括:資料頁、undo頁、系統頁、事

務資料頁、插入緩沖頁等等。

具體的可以參考下圖:

InnoDB體系結構之存儲篇

(摘自知書堂優化班)

既然page是最小的I/O機關。那麼下面看一下page内部的存儲結構以及如何管理。參考下圖:

InnoDB體系結構之存儲篇

(摘自MySQL運維内參)

檔案頭資訊:(摘自MySQL運維内參)

FIL_PAGE_SPACE_OR_CHECKSUM:4位元組。checksum的值

FIL_PAGE_OFFSET:4位元組。表示此頁面是目前表空間得頁面号

FIL_PAGE_PREV:4位元組。上個頁面

FIL_PAGE_NEXT:4位元組。下個頁面

FIL_PAGE_LSN:8位元組。目前頁面最後一次被修改時對應日志的LSN值

FIL_PAGE_TYPE:2位元組。

FIL_PAGE_FILE_FLUSH_LSN:8位元組。目前Innodb最大被FLUSH到的LSN值

FIL_PAGE_ARCH_LOG_NO_OR_SPQCE_ID:4位元組。目前頁面屬于哪個表空間

頁面頭資訊:(摘自MySQL運維内參)

PAGE_N_DIR_SLOTS:2位元組。存儲slot個數

PAGE_HEAP_TOP:2位元組。目前還沒有被使用的空間的最小值

PAGE_N_HEAP:2位元組。目前頁面的記錄數。包括虛拟的最小值最大值

PAGE_FREE:2位元組。已經被删除的記錄所占用的空間組成的連結清單首位址

PAGE_GABAGE:2位元組。已經被标記為删除的記錄數,還沒被purge的。如果被purge就放到page_free裡

PAGE_LAST_INSERT:2位元組。最後被插入的位置

PAGE_DIRECTION:2位元組。和上面的insert有關系,表示插入的方向

PAGE_N_DIRECTION:2位元組。同一個方向連續插入記錄的次數

PAGE_N_RECS:2位元組,目前頁面存儲了多少條記錄

PAGE_MAX_TRX_ID:8位元組。修改目前頁面的所有事務中的最大事務号

PAGE_LEVEL:2位元組。目前節點處于B+樹第幾層

PAGE_INDEX_ID:8位元組。目前頁面屬于哪個索引,存儲的索引ID值

PAGE_BTR_SEG_LEAF:10位元組。頁字段的段頭位址

PAGE_BTR_SEG_TOP:10位元組。内節點段的段頭位址

總之,檔案頭資訊和頁面頭資訊都是為了頁面的安全和高效管理來設定。頭資訊後面就是真正的實體記錄,Innodb存儲引擎中,

最開始的兩條實體記錄永遠都是虛拟的“最小記錄”和“ 最大記錄”。這兩條記錄來限定一個頁面的邊界。并且,在周遊資料的時

候,搜尋到這兩條記錄說明到了頁面的邊界,表示本頁面的周遊已經結束。

在接下來才算到了真正的行(row)記錄。Innodb頁面行的管理是通過slot來實作的。就如上圖所示,一個slot對應一串行記錄,

我們在第一次插入資料頁的時候也許實體上行記錄是有序的,但是通過後面的增删改操作後,實體上這些行記錄其實是已經沒有

順序,但是我們通過修改slot的指針資訊,頁面以及行的頭資訊,來讓行資料繼續有效的管理起來。從上圖也可以看出,槽本身

是排序的,在頁面的最後位置,槽的長度與頁面記憶體儲的記錄數有關系,一個槽占2個位元組。最高位的槽代表索引最小的記錄,

最低位的槽代表索引順序最大的記錄。

圖中還可以看到頁面尾部還存儲了8個位元組,前四個位元組存的是checksum值,後四個位元組存的是頭資訊中的LSN的值。主要作用

是保證頁面的完整性。至此,一個頁面裡的存儲内容以及管理就是這樣管理的。

最後,看一下四中行格式:

Redundant:最早的行格式。

Compact:将長字段超過768位元組的部分off-page存儲。

Dynmic:将長字段完全的off-page存儲,隻存儲20位元組的指針。5.7預設的行格式

Compressed:資料頁壓縮存儲,但buffer pool中的資料不能被壓縮。

繼續閱讀