淺析innoDB數據存儲結構

淺析innoDB數據存儲結構

No.1

引言

 

InnoDB是我們日常開發中最常使用的Mysql存儲引擎,對於這個“老朋友”,你知道他是如何存儲數據記錄的嗎,你知道他是如何建立索引的嗎?本文將會和大家一起深入理解下innoDB數據存儲結構,講講邏輯上的存儲結構和“頁”的數據結構,讓你做innoDB的真兄弟!

 

 

No.2

InnoDB體系結構

 

由圖可知,Mysql數據庫可簡單理解爲3部分

  • 操作文件(數據)的後臺線程

  • 減少cpu與磁盤速度差異的內存池

  • 存儲索引,數據等信息的文件集合

而本文要介紹的innoDB存儲結構實質上就是指innoDB在存儲文件這一部分的數據結構。

數據庫文件中需要存儲哪些數據?

  • 數據

  • 索引

  • 表結構

  • 日誌:包括錯誤日誌,慢查詢日誌,查詢日誌,

    二進制日誌,undo,redo

  • 其他

 

數據庫文件物理分佈

在具體講解邏輯存儲結構前,我們先簡單瞭解下物理上這些文件是怎麼分佈的。物理分佈如下圖所示。

 

  • .frm文件

    此類型文件用於存儲表結構,此結構與使用引擎無關,每張表都存此文件。特別的是當創建一個視圖時,也會生成此類新文件用於記錄視圖的定義。

  • .ibd文件

    此類型文件爲表空間

    • innoDB默認情況下會存在一個10M大小的表空間ibdata1,innoDB管理的表的數據都會存儲在此表空間中

    • 可以通過設置innodb_data_file_path來指定多個文件組成一個表空間,若多個文件不在同一個磁盤下,則可以平均磁盤的負載,提升性能。

    • 可以通過設置innodb_file_per_table來設置每個表生成單獨的ibd表空間,這樣數據就不會存在默認的表空間下了。

特別注意:此處大家可能無法理解表空間是個什麼概念,大家先記住.ibd存儲是表空間文件即可,後面會進行講解。

 

 

No.3

innoDB邏輯存儲結構

 

數據都被邏輯的放到一個空間裏,稱之爲表空間(tablespace),表空間又由段(segment)、區(extent)、頁(page)組成 ,頁innoDB文件管理的最小單位。

  • 一個段256M (不可變)

  • 一個區1M (不可變)

  • 一個頁16K (可變)

  • 一個段=256區=256*64個頁

表空間結構

由上圖可知,表空間是處於結構的最外層。所有的數據都存放在表空間中,文件格式爲.ibd。

特別注意的是,如果我們設置了每個表對應一個表空間,那共享的表空間是不是就沒有用了呢?

答案是否定的,對於每個表獨立的表空間來說只存數據、索引、插入緩衝Bitmap頁,其他如回滾信息、系統事務信息等還在共享表空間中。

 

Segment-段

表空間由各個段組成,常見的段有數據段、索引段、回滾段等 

數據段即葉子節點 

索引段即非葉子節點

Extend-區

區是由連續的頁組成的空間,在任何情況下每個區的大小都是1M,默認情況下每個頁的大小是16KB,即一個區有64個頁。

Page-頁

頁是InnoDB磁盤管理的最小單元,默認每頁16KB,可通過innodb_page_size設置大小爲4K,8K,16K,但設置完成後不可更改。

常見頁類型:

數據頁 , undo頁,系統頁,事務數據頁,插入緩衝位圖頁

插入緩衝空閒列表頁,未壓縮的二進制大對象頁,壓縮的二進制大對象頁

 

段-區-頁組織結構

對於一個表空間來說至少會有個0號頁面(FSP_HDR)用於存儲extend相關的信息,記錄了哪些空閒,哪些滿,哪些有碎片等信息,對於一個FSP_HDR頁來講,只能維護256個extend信息,所以每隔256M就會有一個XDES用來維護下面的區的信息。那爲什麼是256個區呢?下圖分別給出了FSP(XDES)和 XDES entry的結構。

 

由上圖可知,每個區對應40byte的記錄,那16kb扣除其他信息,可存256條記錄,所以一個FSP/XDES頁可存256個區信息,同時也就導致了每個256M就需要有一個XDES頁。

總結一下

綜上所訴,一個表空間有很多頁,爲了更高效對頁進行管理呢,每64個頁劃分爲一組就是區,每256個區再劃分爲一個段,我個人認爲區和段並不是真實存在的,只是一個邏輯概念。

 

 

No.4

INNODB數據頁結構

 

通過上文相信大家對innoDB的數據結構已經有了一個整體上概念,也應該知道了頁是innoDB存儲引擎能操作的最小磁盤單位,頁類型是B-tree的頁存放的即是表中行的實際數據,下面我們繼續深入瞭解數據頁的結構。

組成部分

其中File Header 和 PageHeader 和 Infimun + SupremumRecords,File Trailer是大小固定的用於存儲頁的一些相關信息,其餘的是和數據相關的則爲不定長。

File Header

名稱 

大小(字節) 

說明 

FIL_PAGE_SPACE_OR_CHECKSUM 

代表了頁的checksum值 

FIL_PAGE_OFFSET 

表空間中頁的偏移值 

FIL_PAGE_PREV   

當前頁的上一個頁 

FIL_PAGE_NEXT   

當前頁的下一個頁 

FIL_PAGE_TYPE   

頁類型 

FIL_PAGE_LSN 

該值代表了該頁最後被修改的日誌序列位置 

FIL_PAGE_FILE_FLUSH_LSN 

該值僅在系統表空間定義,獨立表空間爲0 

FIL_PAGE_ARCH_LOG_NO_SPACE_ID 

頁所屬表空間 

頁在邏輯上是連續的,在磁盤中並不是連續的,而是通過上下指針進行邏輯關聯,構成雙向鏈表。但是頁內的物理地址是連續的,頁內的記錄是亂序的單向鏈表。

Page Header

記錄數據頁的狀態信息,14部分組成,共56字節

 

名稱 

大小(字節) 

說明 

PAGE_N_DIR_SLOTS 

Page Directory的Solt數 

PAGE_HEAP_TOP 

指向空閒空間的起始地址 

PAGE_N_HEAP 

頁記錄數,包含已經標記刪除的 

PAGE_FREE 

指向可重用空間的首指針 

PAGE_GARBAGE 

 已刪除記錄總數 

PAGE_LAST_INSERT 

最後插入記錄位置 

PAGE_N_RECS  

頁記錄數,不包含已經標記刪除的

 PAGE_LEVEL 

當前頁在索引數的位置 

PAGE_INDEX_ID  

索引id,當前頁屬於哪個索引 

PAGE_BTR_SEG_LEAF  

10 

B+樹root頁定義,非頁子節點所在段 

PAGE_BTR_SEG_TOP 

10 

B+樹root頁定義,非頁子節點所在段 

todo 差表格

Infimun和SupremunRecords

虛擬的行記錄,可認爲是佔位符,用來限定記錄邊界,Infimun記錄是比該頁主鍵值都要小的值,Supermun是比任何可能大的值還要大的值,兩個記錄在頁創建時候創建 

UserRecords(行記錄)

InnoDB存儲引擎提供了Compact和Redundant兩種格式來存放行記錄數據。redundant是爲了兼容之前版本而保留的我們不做過多研究,我們簡單瞭解下Compact格式。

Compact格式 :compact行記錄格式是從5.0引入,然後mysql5.1開始 Compact成爲了默認的存儲記錄格式。

  • 可以通過SHOW TABLE STATUS LIKE 'table_name',查看當前使用的格式。

  • 可以使用CREATE TABLE 表名(列信息)ROW_FORMAT=COMPACT進行指定行格式。

  • 可以使用ALTER TABLE 表名 ROW_FORMAT = 行格式名稱進行更改行格式

上圖爲Compact行記錄格式。

變長字段長度列表:當列長度小於255時,用一個字節表示,當列長度>255時,用2個字節表示,由此也可以解釋varchar的長度最長爲65535 (2的16次冪),剛好是能記錄的最大長度。

NULL標誌位:很好理解標誌該行數據中是否有空值

記錄頭信息 :如下圖所示

行溢出 :

關於行溢出,即存儲很長的字符串,在該字段會存儲該字符串的前768個字節的前綴(字段超過768字節則爲變長字段),並將整個字符串存儲在uncompress blob頁中。

行分佈

前面說到過,頁的物理地址是連續的,但是頁內數據卻是亂序的,理解起來可能有些抽象,下圖將直觀的展示出頁內行記錄的分佈。

那我們在結合着上文說到的頁和頁之間構成雙向鏈表的關係,下面給出了頁結合行的結構圖。

Page Directory

頁目錄,放了記錄的相對位置,它是一個稀疏目錄,一個目錄指針(solts)包含多個記錄,B+樹索引本身並不能找到具體的一條記錄,B+樹索引能找到只是該記錄所在的頁。數據庫把頁載入內存,然後通過PageDirectory再進行二叉查找。只不過二叉查找的時間複雜度低,同時內存中的查找很快,因此通過忽略了這部分查找所用的時間。

Free Space

這一部分存儲着釋放的空間,這些空間構成了空閒空間鏈表。

BTree

根據上文描述的頁結構最終可構建出innoDB的索引結構圖,索引頁爲非葉節點 ,索引節點中存有對應數據頁的指針, 數據頁爲葉子節點,所以我們通過索引查找記錄,是先定位到頁,再通過頁內的稀疏索引查找對應記錄。

 

END

後期會有專門講解innoDB索引結構的分享哦!別忘了結合本文一起看奧!相信會有1+1>2的效果!

 

特別聲明

本文部分插圖來源於《mysql技術內幕-innoDB存儲引擎第2版》和網絡。

歡迎留言溝通!

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