MYSQL IBD PAGE 頁 磁盤佔用空間 SQL 的計算方式不可靠
- 2020 年 3 月 10 日
- 筆記
問:MYSQL的一個PAGE 頁多大
回答乾脆利索,16K唄,我想這是大多數人的第一個反應和回答,這個回答沒有毛病。但這16k裏面到底有多少是你表中存儲的那些實實在在的數據 ??
這時95%的人肯能已經……
我們都知道,MySql 存儲數據的物理單位,不是行,而是數據頁,默認是一個16KB的數據單元。實際上 MYSQL的頁的大小是可以改變的,可以是8K可以是32K,UNIV_PAGE_SIZE 其實是定義一個MYSQL頁面大小的參數,同時UNIV_PAGE_SIZE_SHIFT也是與修改MYSQL 默認頁大小有關的量,如果你的頁的大小為 16K 則UNIV_PAGE_SIZE_SHIFT的數字必須設置為 14 ,2乘以14次自己,就是16K。(16384)(順便問一句 MYSQL一行能存儲的大小是多少?回味一下)
每個頁面中都會分配一個32位的整數頁碼,通過這個頁碼,頁面之間產生了關係,並且也限制了大小, 232 x 16 KiB = 64 TiB 這就算是一個表最大的存儲容量了。所以一個表的大小與單個頁面之間的關係如官方下面的圖,頁面是一個變量的話,其他都不變。

實際上MYSQL 的頁面存儲的格式也是有分門別類的,在每個數據頁的的文件頁頭中38個位元組不是白佔用的,他主要負責以下的一些功能
1 監測頁面的數據的正確性,FIL_PAGE_CHECKSUM, (還記得MYSQL 廣泛提供的頁面監測的工具嗎) 4 位元組
2 FIL_PAGE_OFFSET ,這個其實可以理解為用頁面組成的表的每頁的編碼,用來看看這個物理的文件到底有多少個頁面,當前你訪問的頁面在整體的位置
4個位元組
3 FIL_PAGE_PREV FILE_PAGE_NEXT ,我們都在說MYSQL是B+ 樹的數據存儲結構,其中這兩個值就表達了 B + 數據樹中的雙向鏈表的形式, 因為他們兩個是指針,指定當前頁面前一個頁面的地址,也指向了當前頁面下一個頁面的地址。所以每個數據頁之間是一個「雙向鏈表」。這對數據的查詢時提取數據是非常重要的。
4 FIL_PAGE_LSN 被修改的日誌序列位置LSN
5 FIL_PAGE_TYPE 當前頁面的類型 頁面是B+樹葉子節點, UNDO LOG ,索引節點,insert buffer空閑列表,insertbuffer位圖, 系統頁面,事務系統數據,BLOB頁面,文件空間頭,擴展描述頁 等
6 LSN_FLUSH_LSN 系統表空間的一個頁中定義,與普通的數據頁面無關
7 FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 頁面數據那個表空間
其中關於當前ibd 文件的中存儲的數據的類型可以通過mysql 自帶的工具
innochecksum 來進行查看,這裡我們打開MYSQL 中的一個ibd文件

在一個MYSQL Per = 1 情況下的頁面,我看可以看到這個文件中 有 1337個索引的頁面,我們的索引節點 INODE PAGE 只有一個,還有452個新分配的頁面,一個insert buffer bitmap 頁面, 1個文件 file spave header
我們將這些數字加在一起,1792 * 16384/1024/1024 = 28MB


從實際當中表的ibd文件,我們也可以驗證。
所以文件的存儲空間與我們的從Ibd文件中導出的數據記錄頁面的信息的組合最終得出的數據存儲頁面大小是一致的。
現在馬上就有一個疑問
問:那這28MB 的數據空間裏面有沒有還可以寫入數據的頁面。
SELECT round((data_length+index_length)/1024/1024,2) FROM information_schema.tables WHERE table_schema='employees' AND table_name='dept_emp';

實際當中通過數據庫的方式SQL的語句來獲得表佔用的數據空間,與通過innochecksum 獲得空間之間是對不上的。
對比一下,目前通過 innochecksum 獲得數據存儲空間佔用是 20.89 MB
而通過語句來獲得是17.09MB
到底哪個更準確
我們對目前的表進行
OPTIMIZE TABLE dept_emp; 讓表中的空間進行一次整理

然後我看一下數值到底有什麼改變,通過SQL 來計算後結果是 24.55


而我們再次通過innochecksum來對ibd文件進行查詢,佔用的數據空間在20.77左右。
同時也做了其他的一些表的空間使用,以及free空間的計算,可以證明通過SQL 來獲得當前表的ibd的空間使用,與實際的表在LINUX下的使用情況是對不上的。
而通過innochecksum 來獲得數據表的使用情況,是比較穩定,並且也是比較準確的。另外OPTIMIZE後會導致通過SQL 來計算表的空間佔用浮動較大,而innochecksum 不會受到影響,並能準確返回實際的磁盤空間使用的情況。