這兩天有空翻了翻大神寫的《innodb存儲引擎》,手癢親身實踐。因爲此書出版了有段時日,沒有用其推薦的python工具,經過點滴推敲,略微發現其中冰山一角的奧祕。對於從此對於一些問題查證或數據遷移可能會有幫助。話很少說,開碼。python
·大結構算法
innodb數據文件按照 :【segment,extent,page,row】層次來組合,中文解釋就是【段、區、頁、行】。
4大元素之間的關係:
Segment=N*[Extent];
Extent=64*Pages;
Page=16KB(Low-Level fs+Page Header+VarcharLength+Data);
Low-Level fs=38 Bytes;
Page-Header=78 Bytes;
Page-Header=【Page Header+虛擬記錄mum】
Data=16*1024B-38B-78B-VcharLength框架
ibd文件由段組成,段有extent能夠按需擴展,truncate能回收空間,但delete只作清零處理。
extent擴展inndo有本身的經驗算法,這塊代碼還沒找到,理論是1-4M,但實際有出現擴從512K突增到9M的狀況。有64個PAGE組成。
Page大小16K,也就是16384個字節。按16進制,UltraEdit下步長起點以下:0000-4000-8000-C000
Page按代碼由3部分組成,邏輯上PageHeader對infimum和supremum有拆分。也能夠說是4部分組成。後面會講。工具
·小結構spa
段和區都爲固定功能且能夠單調遞增,暫不作解釋。主要講一下Page和Row。Row走最多見的compact格式,compact本質取消了必定規則內存對齊操做。
Page的構造以下:
這些結構體的文件系統底層定義在$MYSQL_SRC/storage/include/fil0fil.h中能夠查到,主要這兩個字段在分析中比較有用:翻譯
再往下看,就是PageHeader。它的定義在$MYSQL_SRC/storage/include/page0page.h中能夠查看
從0xc0205的0×0046 space_id開始算起,如上圖所示,是全部page_header的定義和長度。這些定義主要是圍繞了記錄數的起始、大小、長度、位置等作的一些統計信息。
注意圖中的3條紅色虛線,它們分別指出了具體記錄的起點和結束位置。這個位置是相對ROW_ID爲基礎的。
PAGE_HEAP_TOP:記錄整個記錄導出到buf堆時最後的指針停留位置,像上圖中就是c000+00ec=c0ec。
PAGE_LAST_INSERT:記錄着這個PAGE中最後一條記錄的起始位置,像上圖中就是c000+00be=c0be。
INFIMUM虛擬行記錄頭:記錄着第一條記錄的起始位置,像上圖中就是c063+0023=c083。
另外,PAGE_N_RECS:記錄着這個頁中包含着多少條記錄等等。經過這樣1頭1尾定位了全部的記錄框架。
上圖就是與咱們記錄徹底翻譯的16進制解碼,下圖是原始記錄。
對於Row的字段定義在$MYSQL/storage/rem/rem0rec.cc和row0row.cc中有明確解釋。
第一條記錄全字段都被填滿了,因此varchar_length預留了3個字節分別表示了t2,t3,t4存儲的字符長度。
空值判斷預留了1位。這個比較有意思,該值是一個bitmap。這兩段實現能夠rem0rec.cc中查到。
1個字節能夠展現8個字段空與非空。2個字節就能支持到16個字段,以此類推。空了填1,不空填0,從右往左爲視覺字段順序。
Row_ID:默認行記錄key表示。再跟交易trx_ID和回滾指針。
再日後就是varchar的變長真實數據和char的預留數據,char的預留數據爲0×20空格,不是0。這個比較奇怪。
圖中紅、黃、綠分別表明了3條不一樣的記錄,與其自身下圖select對應。指針
至此,咱們就能夠對整個IBD文件進行了初步解析。內存