InnoDB引擎邏輯存儲結(jié)構(gòu)

(本片博文是《MySQL技術(shù)內(nèi)幕 InnoDB存儲引擎第二版》的讀書筆記)

索引組織表

InnoDB存儲引擎中驼鹅,表都是按照主鍵順序組織存放的塌计,這種存儲方式的表稱為索引組織表(index organized table)屯耸。InnoDB存儲引擎表中,每張表都有個主鍵槽袄,若在創(chuàng)建表時沒有顯式定義主鍵則InnoDB存儲引擎會按如下方式選擇或者創(chuàng)建主鍵:

  • 首先判斷表中是否有非空的唯一索引(Unique NOT NULL)凡人,如果有,則該列即為主鍵坪哄。(當(dāng)表中有多個非空唯一索引時质蕉,InnoDB存儲引擎將選擇建表時第一個定義的非空唯一索引為主鍵,注意是根據(jù)定義索引的順序而不是建表時列的順序)翩肌。
  • 如果不符上述條件模暗,則會自動創(chuàng)建一個6字節(jié)大小的指針。

InnoDB邏輯存儲結(jié)構(gòu)

這是《MySQL技術(shù)內(nèi)幕 InnoDB存儲引擎》一書中對InnoDB邏輯存儲結(jié)構(gòu)的描述念祭。


1.PNG

表空間

表空間是Innodb存儲引擎邏輯的最高層兑宇,所有的數(shù)據(jù)都存放在表空間中,默認(rèn)情況下粱坤,Innodb存儲引擎有一個共享表空間ibdata1,即所有數(shù)據(jù)都存放在這個表空間中內(nèi)隶糕。如果啟用了innodb_file_per_table參數(shù),則每張表內(nèi)的數(shù)據(jù)可以單獨放到一個表空間內(nèi)站玄,但請注意枚驻,只有數(shù)據(jù)、索引株旷、和插入緩沖Bitmap放入單獨表內(nèi)再登,其他數(shù)據(jù),比如回滾(undo)信息灾常、插入緩沖檢索頁霎冯、系統(tǒng)事物信息铃拇,二次寫緩沖等還是放在原來的共享表內(nèi)的钞瀑。

從上圖中可以看出表空間由段組成,常見的段有數(shù)據(jù)段慷荔、索引段雕什、回滾段等。因為InnoDB存儲引擎表是索引組織的,因此數(shù)據(jù)即索引贷岸,索引即數(shù)據(jù)壹士。數(shù)據(jù)段即為B+樹的葉子結(jié)點,索引段即為B+樹的非索引結(jié)點偿警。在InnoDB存儲引擎中對段的管理都是由引擎自身所完成躏救,DBA不能也沒必要對其進行控制。

區(qū)

區(qū)是由連續(xù)頁組成的空間螟蒸,在任何情況下每個區(qū)的大小都為1MB盒使。為了保證區(qū)中頁的連續(xù)性,InnoDB存儲引擎一次從磁盤申請4~5個區(qū)七嫌。默認(rèn)情況下少办,InnoDB存儲引擎頁的大小為16KB,一個區(qū)中一共64個連續(xù)的區(qū)诵原。

頁(塊)

頁是InnoDB磁盤管理的最小單位英妓。在InnoDB存儲引擎中,默認(rèn)每個頁的大小為16KB绍赛。從InnoDB1.2.x版本開始蔓纠,可以通過參數(shù)innodb_page_size將頁的大小設(shè)置為4K,8K惹资,16K贺纲。若設(shè)置完成,則所有表中頁的大小都固定褪测,不可以對其再次修改猴誊。除非通過mysqldump導(dǎo)入和導(dǎo)出操作來產(chǎn)生新的庫。
InnoDB存儲引擎中侮措,常見的頁類型有:數(shù)據(jù)頁懈叹,undo頁,系統(tǒng)頁分扎,事務(wù)數(shù)據(jù)頁澄成,插入緩沖位圖頁,插入緩沖空閑列表頁等畏吓。

InnoDB數(shù)據(jù)頁結(jié)構(gòu)

InnoDB數(shù)據(jù)頁結(jié)構(gòu)如下圖:

1.PNG

其中File Header墨状、Page Header、File Trailer的大小是固定的菲饼,分別為38肾砂,56,8字節(jié)宏悦,這些空間用來標(biāo)記該頁的一些信息镐确,如Checksum包吝,數(shù)據(jù)頁所在B+樹索引的層數(shù)等。User Records源葫、Free Space诗越、Page Directory這些部分為實際的行記錄存儲空間,因此大小是動態(tài)的息堂。

1.File Header用來記錄頁的一些頭信息嚷狞,由表中8個部分組成,共占38字節(jié)荣堰。各部分代表信息如下表所示:

1.PNG

2.PNG

2.Page Header用來記錄數(shù)據(jù)頁的狀態(tài)信息感耙,14個部分組成,共占56字節(jié)持隧。各部分代表信息如下表所示:

1.PNG

2.PNG

3.Infimum和Supermum Record是InnoDB中兩個虛擬的行記錄即硼,用來限定記錄的邊界。Infimum記錄是比該頁中任何主鍵值都要小的值屡拨,Supermum是比任何可能大的值還要大的值只酥。這兩個記錄在頁創(chuàng)建時被建立,并且在任何情況下都不會被刪除呀狼。下圖顯示了Infimum記錄和Supermum記錄:
3.PNG

4.User Record和Free Space

User Record就是實際存儲行記錄的內(nèi)容裂允。InnoDB存儲引擎表總是B+樹索引組織的。Free Space指空閑空間哥艇,是鏈表數(shù)據(jù)結(jié)構(gòu)绝编,在一條記錄被刪除后,該空間會被加入到空閑鏈表中貌踏。
5.Page Directory

Page Directory中存放了記錄的相對位置(是頁相對位置而不是偏移量)十饥,有時這些記錄指針稱為Slots(槽)或者目錄槽(Directory Slots)。與其他數(shù)據(jù)庫系統(tǒng)不同的是祖乳,在InnoDB中并不是每個記錄擁有一個槽逗堵,InnoDB存儲引擎的槽是一個稀疏目錄(sparse directory),即一個槽中可能包含多個紀(jì)錄眷昆。偽記錄的Infimum的n_owned值總是為1蜒秤,記錄Supermum的n_owned的取值范圍為[1,8]亚斋,其他用戶記錄n_owned的取值范圍為[4作媚,8]。當(dāng)記錄被插入或刪除時需要對槽進行分裂或平衡的維護操作帅刊。

在Slots中記錄按照索引鍵值順序存放纸泡,這樣可以利用二叉查找迅速找到記錄的指針。假設(shè)有('i','d','c','b','e','g','l','h','f','j','k','a')厚掷,同時假設(shè)一個槽中包含4條記錄弟灼,則Slots中的記錄可能是('a','e','i')。

由于在InnoDB存儲引擎中Page Directory是稀疏目錄冒黑,二叉查找的結(jié)果只是一個粗略結(jié)果田绑,因此InnoDB存儲引擎必須通過recorder header中的next_record來繼續(xù)查找相關(guān)記錄。同時抡爹,Page Directory很好地解釋了recorder header中的n_owned值的含義掩驱,因為這些記錄并不包括在Page Directory中。

B+樹索引本身并不能找到具體的一條記錄冬竟,能找到只是改記錄所在的頁欧穴。數(shù)據(jù)庫把頁載入到內(nèi)存,然后通過Page Directory再進行二叉查找泵殴。只不過二叉查找的時間復(fù)雜度很低涮帘,同時在內(nèi)存中的查找很快,因此通常忽略這部分查找所用的時間笑诅。

6.File Trailer
該部分是為了檢測頁是否已經(jīng)完整地寫入磁盤的(可能在寫入過程中磁盤損壞调缨、機器關(guān)機等)。該部分占用8字節(jié)吆你,前4字節(jié)代表該頁的checksum值弦叶,后4字節(jié)和File Header中的FIL_PAGE_LSN相同。將這兩個值與File Header中的FIL_PAGE_SPACE_OR_CHKSUM和FIL_PAGE_LSN值進行比較妇多,看是否一致(checksum的比較需要通過InnoDB的checksum函數(shù)來比較伤哺,不是簡單的等值比較),以此來保證頁的完整新者祖。

InnoDB存儲引擎是面向列的立莉,也就是說數(shù)據(jù)按行存放。每個頁存放的行記錄也是有硬性定義的七问,最多允許存放16KB/2-200=7992行記錄桃序。
InnoDB存儲引擎提供了Compact和Redundant兩種格式來存放行記錄數(shù)據(jù),Redundant格式是為兼容之前版本而保留的烂瘫。5.1版本中媒熊,默認(rèn)設(shè)置為Compact行格式》乇龋可以通過命令SHOW TABLE STATUS LIKE 'table_name'來查看當(dāng)前表使用的行格式芦鳍,其中row_format屬性表示行記錄類型。

Compact行記錄格式

3.PNG

上圖就是Compact行記錄的存儲方式葛账。由圖可知柠衅,首部是一個非NULL變長字段長度列表,并且是按照列的順序逆序放置的籍琳,長度為:

  • 若列的長度小于255字節(jié)菲宴,用1字節(jié)表示贷祈;
  • 若大于255字節(jié),用2字節(jié)表示喝峦。

變長字段的長度最大不可以超過2字節(jié)势誊,因為在MySQL中VARCHAR類型的最大長度限制為65535。變長字段之后的第二個部分是NULL標(biāo)志位谣蠢,指示了該行數(shù)據(jù)中是否有NULL值粟耻,有則用1表示,占1字節(jié)眉踱。接下來是記錄頭信息挤忙,固定占用5字節(jié)。每位的含義見下表

4.PNG

最后的部分就是實際存儲每個列的數(shù)據(jù)谈喳。NULL不占該部分任何空間册烈,即NULL除了占有NULL標(biāo)志位,實際存儲不占有任何空間婿禽。另外有一點需要注意的是茄厘,每行數(shù)據(jù)除了用戶定義的列外,還有兩個隱藏列谈宛,事務(wù)ID和回滾指針列次哈,分別為6字節(jié)和7字節(jié)的大小。若InnoDB表沒有定義主鍵吆录,每行還會增加一個6字節(jié)的rowid列窑滞。

Redundant行記錄格式

Redundant是MySQL5.0版本之前InnoDB的行記錄存儲方式,MySQL5.0支持Redundant是為了兼容之前版本的頁格式恢筝。Redundant行記錄采用如圖所示的方式存儲哀卫。

1.PNG

首部是字段長度偏移列表,按照列的順序逆序放置撬槽。若列的長度小于255字節(jié)此改,用1字節(jié)表示;若大于255字節(jié)侄柔,用2字節(jié)表示共啃。第二部分為記錄頭信息,占用6字節(jié)暂题,每位含義如下表
2.PNG

從表中可以看出移剪,n_fields值代表一行中列的數(shù)量,占用10位薪者,很好的解釋了為什么MySQL數(shù)據(jù)庫一行支持最多的列為1023纵苛。另一個需要知道的是1byte_offs_flags,該值定義了偏移列表占用1字節(jié)還是2字節(jié)。最后的部分就是實際存儲的每個列的數(shù)據(jù)了攻人。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末取试,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子怀吻,更是在濱河造成了極大的恐慌瞬浓,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烙博,死亡現(xiàn)場離奇詭異,居然都是意外死亡烟逊,警方通過查閱死者的電腦和手機渣窜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宪躯,“玉大人乔宿,你說我怎么就攤上這事》醚” “怎么了详瑞?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長臣缀。 經(jīng)常有香客問我坝橡,道長,這世上最難降的妖魔是什么精置? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任计寇,我火速辦了婚禮,結(jié)果婚禮上脂倦,老公的妹妹穿的比我還像新娘番宁。我一直安慰自己,他們只是感情好赖阻,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布蝶押。 她就那樣靜靜地躺著,像睡著了一般火欧。 火紅的嫁衣襯著肌膚如雪棋电。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天苇侵,我揣著相機與錄音离陶,去河邊找鬼。 笑死衅檀,一個胖子當(dāng)著我的面吹牛招刨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哀军,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼沉眶,長吁一口氣:“原來是場噩夢啊……” “哼打却!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谎倔,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤柳击,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后片习,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捌肴,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年藕咏,在試婚紗的時候發(fā)現(xiàn)自己被綠了状知。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡孽查,死狀恐怖饥悴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盲再,我是刑警寧澤西设,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站答朋,受9級特大地震影響贷揽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梦碗,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一擒滑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叉弦,春花似錦丐一、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至樱拴,卻和暖如春柠衍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背晶乔。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工珍坊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人正罢。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓阵漏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子履怯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容