文章目錄
- 一、InnoDB 資料頁存盤結構
- 1. File Header
- 2. Page Header
- 3. Infimun Records 和 Supremum Records
- 4. User Records
- 5. Free Space
- 6. Page Directory
- 7. File Trailer
一、InnoDB 資料頁存盤結構
innodb 存盤引擎資料頁結構如圖所示:

InnoDB 資料頁由 7 個部分組成:
- File Header :檔案頭
- Page Header:頁頭
- Infimun 和 Supremum Records
- User Records:用戶記錄,即行記錄
- Free Space:空閑空間
- Page Directory:頁目錄
- File Trailer:檔案結尾資訊
1. File Header
File Header用來記錄頁的一些頭資訊,共占用 38 個位元組,具體記錄了哪些資訊如下表所示:
| 名稱 | 大小 | 說明 |
|---|---|---|
| FIL_PAGE_SPACE_OR_CHKSUM | 4 | MySQL 版本 4. 0 之前該值為 0,版本 4.0 之后該值代表頁的 checksum 值 |
| FIL_PAGE_OFFSET | 4 | 表空間中頁的偏移量,表示當前頁在所有頁中的偏移量,例如(10,1)表示查找表空間 ID 為 10 的第二個頁 |
| FIL_PAGE_PREV | 4 | 當前頁的上一個頁,B+ 樹的葉子節點之間鏈接形成雙向鏈表 |
| FIL_PAGE_NEXT | 4 | 當前頁的下一個頁,B+ 樹的葉子節點之間鏈接形成雙向鏈表 |
| FIL_PAGE_LSN | 8 | 代表當前頁最后被修改的日志序列位置 |
| FIL_PAGE_TYPE | 2 | InnoDB 存盤引擎頁的型別 |
| FIL_PAGE_FILE_FLUSH_LSN | 8 | 該值僅僅在 系統表空間 的一個頁中定義,對于獨立表空間該值為0,含義是檔案至少被更新到了該 LSN 值 |
| FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID | 4 | MySQL 版本 4.1 之后,該值表示頁屬于哪個表空間 |
FIL_PAGE_TYPE的取值和含義如下表所示:
/** File page types (values of FIL_PAGE_TYPE) @{ */
#define FIL_PAGE_INDEX 17855 /*!< B-tree node */
#define FIL_PAGE_RTREE 17854 /*!< B-tree node */
#define FIL_PAGE_UNDO_LOG 2 /*!< Undo log page */
#define FIL_PAGE_INODE 3 /*!< Index node */
#define FIL_PAGE_IBUF_FREE_LIST 4 /*!< Insert buffer free list */
/* File page types introduced in MySQL/InnoDB 5.1.7 */
#define FIL_PAGE_TYPE_ALLOCATED 0 /*!< Freshly allocated page */
#define FIL_PAGE_IBUF_BITMAP 5 /*!< Insert buffer bitmap */
#define FIL_PAGE_TYPE_SYS 6 /*!< System page */
#define FIL_PAGE_TYPE_TRX_SYS 7 /*!< Transaction system data */
#define FIL_PAGE_TYPE_FSP_HDR 8 /*!< File space header */
#define FIL_PAGE_TYPE_XDES 9 /*!< Extent descriptor page */
#define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */
#define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */
#define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */
#define FIL_PAGE_TYPE_UNKNOWN 13 /*!< In old tablespaces, garbage in FIL_PAGE_TYPE is replaced with this value when flushing pages. */
#define FIL_PAGE_COMPRESSED 14 /*!< Compressed page */
#define FIL_PAGE_ENCRYPTED 15 /*!< Encrypted page */
#define FIL_PAGE_COMPRESSED_AND_ENCRYPTED 16/*!< Compressed and Encrypted page */
#define FIL_PAGE_ENCRYPTED_RTREE 17 /*!< Encrypted R-tree page */
| 常量名稱 | 十六進制 | 含義 |
|---|---|---|
| FIL_PAGE_INDEX | 0x45BF | B+ 數葉子節點(資料節點) |
| FIL_PAGE_UNDO_LOG | 0x0002 | undo log 頁 |
| FIL_PAGE_INODE | 0x0003 | 索引節點 |
| FIL_PAGE_IBUF_FREE_LIST | 0x0004 | insert buffer 空閑串列頁 |
| FIL_PAGE_TYPE_ALLOCATED | 0x0000 | 最新分配還未使用的頁 |
| FIL_PAGE_IBUF_BITMAP | 0x0005 | insert buffer 位圖頁 |
| FIL_PAGE_TYPE_SYS | 0x0006 | 系統頁 |
| FIL_PAGE_TYPE_TRX_SYS | 0x0007 | 事務系統資料頁 |
| FIL_PAGE_TYPE_FSP_HDR | 0x0008 | File Space Header 頁 |
| FIL_PAGE_TYPE_XDES | 0x0009 | 擴展描述頁 |
| FIL_PAGE_TYPE_BLOB | 0x000A | BLOB 頁 |
2. Page Header
Page Header 用來記錄資料頁的狀態資訊,共占用 56 位元組,具體資訊如下表所示:
| 名稱 | 大小(位元組) | 說明 |
|---|---|---|
| PAGE_N_DIR_SLOTS | 2 | 表示頁目錄(Page Directory)中的槽(Slot)數量 |
| PAGE_HEAP_TOP | 2 | 記錄在頁中是以堆的形式存放的,該值存放的是指向第一個記錄的指標 |
| PAGE_N_HEAP | 2 | 堆中的記錄數,一共占用 2 個位元組 |
| PAGE_FREE | 2 | 指向可重用空間的首指標 |
| PAGE_GARBAGE | 2 | 行記錄中 delete flag 為 1 的總位元組數,即被洗掉的記錄的大小總和 |
| PAGE_LAST_INSERT | 2 | 最后插入記錄的位置 |
| PAGE_DIRECTION | 2 | 最后插入的方向 |
| PAGE_N_DIRECTION | 2 | 一個方向連續插入記錄的數量 |
| PAGE_N_RECS | 2 | 該頁中記錄的數量 |
| PAGE_MAX_TRX_ID | 8 | 修改當前頁的最大事務ID,注意該值僅在 Secondary Index 中定義 |
| PAGE_LEVEL | 2 | 當前頁在索引樹中的位置,0x00表示葉節點 |
| PAGE_INDEX_ID | 8 | 索引ID,表示當前頁屬于哪個索引 |
| PAGE_BTR_SEG_LEAF | 10 | B+ 樹資料頁非葉節點所在段的 segment header |
| PAGE_BTR_SEG_TOP | 10 | B+ 樹資料頁所在段的 segment header |
3. Infimun Records 和 Supremum Records
Infimun 記錄是比該頁中任何主鍵值都要小的值,Supremum 記錄是比任何可能大的值還要大的值,這兩個值在頁創建時被建立,并且在任何情況下都不會被洗掉,這兩個記錄位于頁中的所有航記錄資料的收尾處,如圖所示:

4. User Records
User Records實際存盤行記錄的內容,如圖:

5. Free Space
Free Space指的是空閑空間,同樣也是使用鏈表來進行組織的,在一條記錄被洗掉后,該空間會被自動加入到空閑串列中
6. Page Directory
Page Directory顧名思義是這個頁的所有記錄的一個目錄,存放著數量可變的記錄指標,這些指標指向頁中存放的記錄,有時記錄指標被稱為槽,所以Page Directorty有時被稱為目錄槽,在InnoDB頁面中并不是一個記錄指標對應一個記錄,而是若干個(1~8)記錄對應一個記錄指標,在完整的頁面中,每六條記錄將有一個槽,
記錄的頭資訊中有一個大小為4位的n_owned,表示管理當前記錄的槽一共管理了多少個記錄,
舉例:如果一個頁中的記錄是‘A’、‘B’、‘F’、‘D’,記錄指標將是(pointer to ‘A’)、(pointer to ‘B’)、(pointer to ‘D’)、(pointer to ‘F’)

由舉例可知,指標的排列順序是按照鍵值的順序排列的,故在查找某一條記錄時,可以通過二分查找的方式進行查找
所以查找一條記錄的程序為:先在 B+ 樹上定位到記錄所在的葉子節點(資料頁),然后將整個資料頁載入到記憶體中,然后在目錄槽中進行二分查找目標記錄所在的槽,然后在槽所管理的若干條記錄中尋找目標記錄
7. File Trailer
為了檢測頁向磁盤中寫入的程序中是否產生損壞,在 InnoDB 存盤引擎頁中設定了 File Trailer 來做檢驗,
File Trailer 組成:只有一個 FIL_PAGE_END_LSN 部分,占用 8 位元組,前 4 位元組代表此頁的 checksum 值,最后 4 位元組和 File Header 中的 FIL_PAGE_LSN 相同

檢查原理:將 8 位元組的 File Trailer 與 File Header 中的 FIL_PAGE_SPACE_OR_CHKSUM 和 FIL_PAGE_LSN 組成的 8 位元組作比較(并不是簡單的等值比較,而是需要通過檢查 checksum 的演算法),
檢查 checksum 的演算法:通過引數innodb_checksum_algorithm 來控制,可設定的演算法有:crc32、none、strict_innodb、strict_crc32、strict_none,其中strict_*的演算法表示嚴格按照設定的演算法進行頁的檢測
MySQL [(none)]> show variables like 'innodb_checksum_algorithm'\G;
*************************** 1. row ***************************
Variable_name: innodb_checksum_algorithm
Value: crc32
1 row in set, 1 warning (0.08 sec)
是否開啟對頁的完整性檢查由引數innodb_checksums控制:
MySQL [(none)]> show variables like 'innodb_checksums'\G;
*************************** 1. row ***************************
Variable_name: innodb_checksums
Value: ON
1 row in set, 1 warning (0.00 sec)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/393908.html
標籤:java
