索引組織表
聚集索引, 隱式row_id
表邏輯結構:表空間-段-區-頁-行
-
段
-
葉子節點段(數據段)
新建的數據段只有32個頁(16K)的碎片頁,不足一個區,用完后在分配連續的區
非葉子節點段(索引段)
undo段
-
區,區是連續的頁,一個區大小為 1M
-
頁,也叫塊,innodb 磁盤管理的最小單位。存儲頁大小為 16K,即一個區有96個頁。
數據頁(B-tree Node)
undo頁(undo Log Page)
系統頁(System Page)
事務數據頁(Transaction system Page)
插入緩沖位圖頁(Insert Buffer Bitmap)
插入緩沖空閑列表頁(Insert Buffer Free List)
未壓縮的二進制大對象頁(Uncompressed BLOB Page)
壓縮的二進制大對象頁(compressed BLOB Page)
行,每個頁最多允許存放16KB/2-200行的記錄,即7992行記錄
行結構
compact 格式
變長字段長度
每個變長字段長度最大2字節表示,也就是變長字段最大 65536 byte
列表以逆序順序表示。如實例 line1,第一個變長字段長度是1,第二個是 3
null 標志位
初始1字節。若有超過8個字段可以為 null,則增加一個字節表示。詳見這篇文章
只關心可以為 null 的字段,每個 bit 標志一個可為 null 的字段,逆序排列。
null 在數據里不占據實際空間,只是有一個 bit 作為標記
記錄頭
delete_flag 表示已經被標記刪除(并不是SQL delete的時候立即物理刪除,有后臺線程定時清理、合并空間)
當前記錄是否是當前頁最小虛擬記錄
-
record_type
000,表示普通記錄
001,表示B+樹非葉子節點
010,infimum
011,supremum
next_record,下一條數據的相對偏移量,占 2 字節。同時意味著當前記錄,在當前空間的最大長度是 2^16,也就是 25536 字節
reduntant 格式
略
行溢出數據
* 不定長數據到底如何存儲?前面說過,下一條數據偏移量占2字節,也就是說,當前數據長度最多 25535 字節,varchar 最大也是 25535,那么一條記錄能存下一條 25535 的 varchar 嗎?
如圖:

換個編碼:
從圖中可以看出,varchar 的限制單位是字節,而不是一個字,utf8 通常按3個字節表示,所以圖中最大是 21845。實測中發現有的SQL工具可以執行成功以上的創建命令,但是檢查表信息,發現把字段 a 標記成了 text 類型。
當行數據大小超過 25535 時,會發生行溢出。行溢出時,數據存放在頁類型為Uncompress BLOB頁中
-
數據庫的每個數據頁大小為 16K,而行最大的長度是 65535,也就是 64K,那么行數據會跨頁存儲嗎?
數據庫通常是以 ID 為聚集索引,構建 B+ 樹,而葉子節點的最小單位是頁。也就是說,索引只是找到對應數據頁,具體是頁中的那一條行記錄,是加載數據頁到內存,然后遍歷得出。
而作為 B+ 樹節點,至少應該有兩條記錄(否則失去了 B+ 樹的意義,變成了鏈表),因此當數據頁只能存下一條行記錄,InnoDB 會自動把該行溢出。所以,每條行記錄實際存儲在數據頁(B+樹葉子節點)中的大小,最多 8K (實際還要小一點,因為還有頁的屬性的字段要存),溢出的數據,會被放到 Uncompressed BLOB Page。
char 和 varchar
通常認為 char 是定長的,varchar 是變長的。但是有些細節還是要注意
char 的 limit 單位是字符,而不是字節。如 char(2) 在 utf8 字符集下可以存 “你好”,實際占用占用 6 字節。不足 2 字符的,會在前面自動填充 0x20
varchar 的 limit 單位是字節
char 會和 varchar 一樣,在變長字段長度列表中,記錄字符串真實長度
頁結構
-
File header
File type, 頁的類型,有數據頁、索引頁、系統頁、事務數據頁、BLOB頁 等等
Page_prev 和 Page_next,前一個頁和后一個頁的指針(B+樹的特性決定葉子節點是雙向鏈表)
Page offset,int32,頁的偏移量,表示當前頁的 ID,2^32 * 16KB = 64 TB,64TB 就是 Innodb 理論上最大的存儲限制
Page header,有不少字段,主要是用來管理可用空間的
Infimum & supremum,是兩個虛擬的記錄,行記錄在頁中是以鏈表的形式存儲,這兩個記錄可以看作鏈頭和鏈尾
User records, 實際的行記錄數據
Free space,空閑空間,數據被刪除后,該空間會被加入到這個鏈表
page directory,業內記錄的稀疏目錄,用于加載到內存后的二分查找
file trailer,最主要的字段是 checksum,校驗和,用于判斷頁的數據是否完整寫入到磁盤