首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

InnoDB 表空間管理源碼級解析:Space、Segment、Extent、Page 四層架構

     編輯:MySQL 綜合教學

概覽

InnoDB 表空間採用邏輯分層:**Space (表空間) → Segment (段) → Extent (區) → Page (頁)**。最小分配單位為 Page (默認 16KB),Extent 固定 64 Pages (1MB),Segment 由多個 Extent + 32 個碎片頁組成。底層通過**磁盤雙向鏈表** 管理邏輯關係。

一、磁盤鏈表結構 (fil0lst.*)

// 地址定位結構
typedef struct fil_addr_t {
  ulint page;    // Space 內頁號
  ulint boffset; // 頁內字節偏移 (2 字節)
} fil_addr_t;

// 鏈表節點 (12 字節)
struct flst_node_t {
  fil_addr_t prev; // 前驅
  fil_addr_t next; // 後繼
};

// 鏈表基節點 (頭信息)
struct flst_base_node_t {
  uint32 len;      // 節點數
  fil_addr_t first; // 首節點
  fil_addr_t last;  // 尾節點
};

通過 fil_addr_t + Buffer Pool 映射 可 O(1) 定位內存節點。

二、Space 結構詳解

1. FSP_HDR / XDES 頁 (第 0 頁及每 16384 頁)

  • 前 112 字節:File Space Header (FSP Header)
  • 剩餘空間:Extent Descriptor (XDES) 陣列,每頁最多 256 個 XDES,每個對應 1 Extent。

XDES Entry 結構 (40 字節)

struct xdes_t {
  fil_addr_t fseg_id;   // 所屬 Segment ID
  flst_node_t list;     // 磁盤鏈表節點 (Free/Free_Frag/Full_Frag/FSEG)
  uint32 state;         // XDES_FREE / XDES_FREE_FRAG / XDES_FULL_FRAG / XDES_FSEG
  uint32 bitmap[16];    // 64 pages × 2 bits (used, clean)
};

FSP Header 關鍵字段

字段含義
space_id表空間 ID
size最大頁數 (擴容時更新)
limit已初始化頁數
free完全空閒 Extent 鏈表
free_frag有碎片頁空閒 Extent 鏈表
full_frag無空閒頁 Extent 鏈表
seg_id下一可用 Segment ID
full_inode_list / free_inode_listInode 頁鏈表

2. FSEG Inode 頁

  • 每頁 85 個 Inode (192 字節/個),管理一個 Segment 的 Extent 與碎片頁。
  • Inode 結構:
struct fseg_inode_t {
  uint32 fseg_id;           // Segment ID
  uint32 n_used;            // Not_full 鏈表已用頁數
  flst_node_t free;         // 空閒 Extent 鏈表
  flst_node_t not_full;     // 部分使用 Extent 鏈表
  flst_node_t full;         // 滿 Extent 鏈表
  uint32 magic_n;           // 校驗魔數
  uint32 frag_arr[32];      // 碎片頁頁號陣列 (新建表先分配 32 頁碎片)
};

三、Space 邏輯架構圖

Space (Tablespace)
├── Page 0: FSP_HDR + XDES[0..255] (Extent 0..255)
├── Page 16384: XDES[256..511]
├── ...
├── Inode Pages (管理 Segment)
│   ├── Inode 0 → Segment 0 (B+Tree 索引/數據)
│   ├── Inode 1 → Segment 1 (Undo Log)
│   └── ...
└── Data Pages (葉子頁/非葉子頁/Undo 頁/臨時頁 ...)

四、分配流程源碼邏輯 (fsp0fsp.*)

1. Inode 分配 (fsp_alloc_seg_inode)

  1. 嘗試從 FSP_SEG_INODES_FREE 鏈表獲取有空槽的 Inode 頁。
  2. 無則從 FSP_FREE 分配新 Inode 頁 (fsp_alloc_seg_inode_page)。
  3. 從 Inode 頁取出一個空 Inode,初始化。
  4. 若 Inode 頁滿,移至 FSP_SEG_INODES_FULL。

2. Extent 分配 (兩種路徑)

路徑 A:Segment 內分配 (fseg_alloc_free_page_low)

Inode 管理,按優先級:

  1. Hint 頁空閒 → 直接返回。
  2. Free Extent 存在且碎片頁耗盡 → 分配 1/5 Extent (視 Segment 大小)。
  3. Not_full Extent 有空頁 → 返回。
  4. 其他 Not_full Extent → 返回。
  5. 碎片頁陣列有空 → 返回。
  6. 向 Space Free 列表申請新 Extent → 返回。

路徑 B:碎片頁分配 (臨時/小表)

直接操作 Space 級 FSP_FREE_FRAG / FSP_FULL_FRAG 鏈表,不經 Inode,適合小對象 (如臨時表)。

3. Page 分配

Extent 內通過 Bitmap 掃描首個 used=0 頁,設置 used=1,更新 n_used,若 Extent 滿則移動鏈表節點 (Free→Not_full→Full)。

五、關鍵源碼文件映射

文件職責
fsp0fsp.c/h表空間核心管理 (分配/釋放/擴容/校驗)
fil0fil.c/h文件 I/O 抽象層 (打開/關閉/讀寫/同步)
page0page.c/h頁操作 (解析/壓縮/校驗/目錄槽)
fseg0fseg.c/hSegment 操作 (創建/擴展/釋放/碎片管理)
buf0buf.c/hBuffer Pool 頁緩存管理

六、實戰啟示

  1. 大表預分配: ALTER TABLE ... AUTO_INCREMENT=N 可減少擴容頻率。
  2. 碎片整理: OPTIMIZE TABLE 觸發重建,釋放碎片 Extent 回 Free 列表。
  3. 獨立表空間: innodb_file_per_table=1 使每表獨立 .ibd,便於遷移/截斷/備份。
  4. 監控指標: Innodb_tablespace_free, Innodb_tablespace_used, Innodb_fseg_* (需啟用監控插件)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved