<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
「頁」是InnoDB管理儲存空間的基本單位,也是記憶體和磁碟互動的基本單位。也就是說,哪怕你需要1位元組的資料,InnoDB也會讀取整個頁的資料,下次讀取的資料如果恰巧也在這個頁裡,就能命中快取了。寫也是一樣的,寫資料前要先把頁載入到記憶體,然後在記憶體中修改,該頁被記為「髒頁」,髒頁淘汰之前必須刷盤。
InnoDB有很多型別的頁,它們的用處也各不相同。比如:有存放undo紀錄檔的頁、有存放INODE資訊的頁、有存放Change Buffer資訊的頁、存放使用者記錄資料的頁等等。今天我們要聊的,就是最基礎也是最重要的,存放使用者記錄資料的「索引頁」。
InnoDB預設的頁大小是16KB,在初始化表空間之前可以在組態檔中進行設定,一旦初始化完成就不可再變更了。檢視頁大小的命令如下,顯示的是位元組數。
SHOW VARIABLES LIKE 'innodb_page_size';
索引頁結構如下圖所示:
索引頁由七部分組成,其中Infimum和Supremum也屬於記錄,只不過是虛擬記錄,這裡為了與使用者記錄區分開,還是決定將兩者拆開。
名稱 | 大小 | 描述 |
---|---|---|
File Header | 38位元組 | 所有頁的通用檔案頭資訊 |
Page Header | 56位元組 | 索引頁特有的頁頭資訊 |
Infimum+Supremum | 26位元組 | 頁中虛擬的最小、最大記錄 |
User Records | 變長 | 使用者記錄資料 |
Free Space | 變長 | 空閒空間 |
Page Directory | 變長 | 頁目錄,加速頁內資料檢索效率 |
File Trailer | 8位元組 | 所有頁的通用檔案尾資訊,校驗頁是否完整 |
File Header是所有頁都有的一個通用的結構,佔用固定的38位元組,它記錄了頁的一些通用的狀態資訊,例如:頁的頁號、Checksum、把頁串聯成雙向連結串列的指標、頁的型別等等。
名稱 | 大小 | 描述 |
---|---|---|
FIL_PAGE_SPACE_OR_CHECKSUM | 4位元組 | 新版本中代表頁的校驗和Checksum |
FIL_PAGE_OFFSET | 4位元組 | 頁號 |
FIL_PAGE_PREV | 4位元組 | 上一個頁的頁號 |
FIL_PAGE_NEXT | 4位元組 | 下一個頁的頁號 |
FIL_PAGE_LSN | 8位元組 | 頁面最後被修改時的LSN值 |
FIL_PAGE_TYPE | 2位元組 | 頁的型別 |
FIL_PAGE_FILE_FLUSH_LSN | 8位元組 | 僅在系統表空間的第1個頁中使用,代表檔案至少被重新整理到了對應的LSN值 |
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID | 4位元組 | 頁資料哪個表空間 |
FIL_PAGE_SPACE_OR_CHECKSUM
基於當前頁計算出的校驗和(Checksum),可以把它看作是雜湊值,校驗和不同,則兩個頁資料肯定不同。它的作用是InnoDB在髒頁刷盤時,有可能會遇到頁刷到一半斷電的情況,頁的頭和尾部分分別記錄校驗和,只有當頭尾的校驗和一致的時候,才代表磁碟上的頁是完整的,否則就是一個損壞的頁。
FIL_PAGE_OFFSET
頁號,頁的唯一標識,全域性遞增的數位,InnoDB通過頁號來定位唯一的一個頁。4位元組儲存,意味著一個表空間最多可以有232個頁,按照一個頁16KB計算,則一個表空間最多支援64TB的資料。
FIL_PAGE_PREV & FIL_PAGE_NEXT
一個頁大小才16KB,一張表資料其實是由N多個頁構成的,頁與頁之間在物理上可以是不連續的,但是邏輯上要連續,FIL_PAGE_PREV和FIL_PAGE_NEXT分別指向當前頁的上一個頁和下一個頁的頁號,通過這兩個指標將索引頁串聯成了一個雙向連結串列。記錄與記錄之間是單向的,頁與頁之間是雙向的!
FIL_PAGE_LSN
頁面最後被修改時,對應的LSN值。LSN的全稱是Log Sequence Number,紀錄檔序列號。它是一個遞增的數位,和事務相關,這裡不作贅述。
FIL_PAGE_TYPE
當前頁的型別,InnoDB為了不同的目的設計了很多不同型別的頁,索引頁的固定值是0x45BF
。
FIL_PAGE_FILE_FLUSH_LSN
僅在第1個頁中使用,用來判斷資料庫是正常關閉還是異常宕機。
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID
僅記錄當前頁資料哪個表空間。
Page Header是索引頁特有的結構,佔用固定的56位元組,它記錄了索引頁中記錄相關的狀態資訊。
名稱 | 大小 | 描述 |
---|---|---|
PAGE_N_DlR_SLOTS | 2位元組 | 頁目錄中的槽數量 |
PAGE_HEAP_TOP | 2位元組 | 未使用的空間最小地址,User Records和Free Space分界點 |
PAGE_N_HEAP | 2位元組 | 本頁中的記錄的數量(包括虛擬記錄和刪除記錄) |
PAGE_FREE | 2位元組 | 第一個刪除的記錄地址,後續刪除的記錄會形成連結串列。 |
PAGE_GARBAGE | 2位元組 | 已刪除記錄佔用的位元組數 |
PAGE_LAST_INSERT | 2位元組 | 最後插入記錄的位置 |
PAGE_DIRECTION | 2位元組 | 記錄插入的方向 |
PAGE_N_DIRECTION | 2位元組 | 同一個方向連續插入的記錄數量 |
PAGE_N_RECS | 2位元組 | 該頁中記錄的數量(不包括虛擬記錄和刪除記錄) |
PAGE_MAX_TRX_ID | 8位元組 | 修改當前頁的最大事務ID,僅在二級索引中使用 |
PAGE_LEVEL | 2位元組 | 當前頁在B+樹中所處的層級 |
PAGE_INDEX_ID | 8位元組 | 索引ID,表示當前頁屬於哪個索引 |
PAGE_BTR_SEG_LEAF | 10位元組 | B+樹葉子段的頭部資訊,僅在B+樹的Root頁定義 |
PAGE_BTR_SEG_TOP | 10位元組 | B+樹非葉子段的頭部資訊,僅在B+樹的Root頁定義 |
不用每個屬性都瞭解,我們挑幾個比較重要的看看。
PAGE_N_DlR_SLOTS
一個頁內可能有上千條記錄,挨個遍歷的話效率太慢了。為了提高頁內記錄的檢索效率,InnoDB將頁內的記錄劃分為多個組,組裡最大的那條記錄相較於頁的地址偏移量會記錄到「Page Directory」部分,每個組都對應一個槽,槽的大小是固定的2位元組。該屬性記錄的就是頁內槽的數量。
PAGE_HEAP_TOP
Free Space的起始位置,它是User Records和Free Space分界點。一個全新的頁一開始是沒有User Records部分的,每插入一條記錄,都要向Free Space申請空間,Free Space耗盡就代表頁滿了。
PAGE_FREE
DELETE命令刪除記錄時,InnoDB並不會真的將記錄從磁碟中刪除,而是在記錄的頭資訊裡打個標記,然後將其加入到「垃圾連結串列」中。PAGE_FREE指向的就是垃圾連結串列的表頭記錄。後面刪除的記錄,也會自動加入到連結串列裡。
PAGE_DIRECTION & PAGE_N_DIRECTION
PAGE_DIRECTION表示最後一條記錄插入的方向,比上一條記錄值大則記為右邊,反之則是左邊。PAGE_N_DIRECTION表示同一方向連續插入的記錄數,方向變了該值就會重置。
PAGE_LEVEL
InnoDB組織資料的形式就是B+樹,樹中的節點就是索引頁,PAGE_LEVEL代表當前頁在B+樹中所處的層級。InnoDB規定,葉子節點層級為0,然後向上遞增。
Infimum和Supremum也屬於記錄,只是為了與使用者記錄區分開才劃分成了兩部分,我們先看User Records。
使用者記錄存放在User Records部分,一個全新的頁一開始全是Free Space,是沒有User Records部分的。每插入一條記錄都需要到Free Space申請一塊空間,並將其劃分到User Records用來存放使用者記錄。當Free Space耗盡也就代表當前頁已經用完了,再有新記錄需要插入,就需要申請一個新的頁了。
還記得MySQL的行格式嗎?它決定了記錄在磁碟裡的儲存格式。以COMPACT為例,儲存格式如下圖:
記錄頭資訊裡的欄位比較關鍵,以防大家忘記,我這裡再貼一下:
名稱 | 大小(Bit) | 說明 |
---|---|---|
預留位1 | 1 | 沒有使用 |
預留位2 | 1 | 沒有使用 |
deleted_flag | 1 | 記錄刪除標記 |
min_rec_flag | 1 | B+樹非葉子節點的最小目錄項標記 |
n_owned | 4 | 同一頁內同一組裡最大的記錄會記錄組裡的記錄數量,其餘記錄該值為0 |
heap_no | 13 | 當前記錄在頁面堆裡的相對位置 |
record_type | 3 | 記錄型別。0:普通記錄,1:B+樹非葉子節點目錄項記錄,2:Infimum記錄,3:Supremum記錄. |
next_record | 16 | 下一條記錄的相對位置 |
記錄頭資訊的最後2位元組用來連線下一條記錄,將頁內所有記錄串聯成一個單向連結串列。所以我們隱藏變長欄位長度列表和NULL值列表,記錄的格式應該是這樣的:
記錄是怎麼排序的?
我們已經知道,頁內的記錄會自動串聯成一個單向連結串列。那這個連結串列的編排順序是什麼呢?是按照記錄的插入時間排序的嗎?其實不是的,如果表有主鍵,會根據主鍵排序;沒主鍵有唯一非空索引,會根據該索引排序;兩者都沒有,InnoDB會自動生成一個row_id
列並根據該列進行排序。
若無特殊說明,本文均假定表有主鍵。
Infimum和Supremum是索引頁內的兩條虛擬記錄,InnoDB規定所有索引頁都會有這兩條記錄,而且所有的使用者記錄都比Infimum大,都比Supremum小。
記錄頭資訊裡的heap_no代表記錄在堆裡的相對位置,該值越小代表記錄越靠前。細心的同學會發現,上圖中的使用者記錄heap_no值是從2開始的,那0和1呢?不說你也肯定猜到了,就是被Infimum和Supremum佔用了。Infimum和Supremum的heap_no值分別是0和1,它倆在所有使用者記錄的最前面。
Infimum和Supremum結構非常的簡單,和使用者記錄一樣也有頭資訊,真實資料部分是固定的字串,如下圖所示:
我們把這兩條虛擬記錄也加入到記錄裡面,完整的結構就是下面這樣的:
Supremum記錄的next_record屬性為0,代表它已經沒有下一條記錄了。
Free Space沒什麼好說的,就是一塊未被使用的空閒空間。
Page Directory也叫作「頁目錄」,它的目的是提高頁內記錄的檢索效率。相較於一張表幾千萬的記錄來說,一個頁內幾百上千條記錄已經是很少很少了。可即便如此,它也有幾百上千條啊,如果頁內檢索記錄只能挨個遍歷的話,那也太低效了。別忘了,頁內的記錄是根據索引值排好序的,我們可以巧用「二分法」來快速查詢。
具體做法是:將頁內所有非刪除的記錄劃分為N個組,每個組裡最後一條記錄(即主鍵最大的記錄)稱作“大哥”,其餘記錄是“小弟”,“大哥”的n_owned
屬性記錄了組內的記錄數量。將“大哥”在頁內的地址偏移量提取出來,按順序依次從File Trailer部分往前寫,每個地址偏移量佔用2位元組,稱作一個「槽」,Page Directory就是由這些槽構成的。
InnoDB對於分組內的記錄數量有一些規定:
由此可見,一個組裡最多有8條記錄,只要通過二分法快速定位到組,InnoDB也只需要遍歷這8條記錄,相較於遍歷頁內所有記錄,效率要高的多。
File Trailer是所有頁都有的通用結構,佔用固定的8位元組,它的主要作用就是為了校驗頁的完整性。磁碟的速度實在是太慢了,InnoDB不會每次寫點資料都直接重新整理到磁碟上,那樣MySQL會慢死。而是將頁作為刷盤的基本單位,資料修改時,先改記憶體裡的頁,稍後再將整個頁的資料一次性重新整理到磁碟裡。但是這會帶來一個問題,一個頁16KB,刷到第10KB的時候磁碟斷電了怎麼辦?重啟後InnoDB如何判斷磁碟裡的頁資料是完整的?
InnoDB是這麼處理的,刷盤前根據頁資料計算出一個Checksum,在頁頭和頁尾都寫一份。頁刷盤的時候,先刷頁頭再刷頁尾,當頭尾兩個Checksum值一致的時候,代表磁碟裡的頁是完整的,否則就表示頁頭刷了頁尾沒刷,那肯定是刷到一半出錯了。
大小 | 說明 |
---|---|
4位元組 | 頁的校驗和Checksum |
4位元組 | 頁最後被修改時對應的LSN的後4個位元組,正常情況下應該與File Header裡的FIL_PAGE_LSN的後4個位元組相同。 |
頁是InnoDB存取資料的基本單位,預設頁大小是16KB,InnoDB為了不同的目的設計了很多不同型別的頁,本文重點分析了存放使用者記錄的索引頁。頁的頭尾部分File Header和File Trailer是所有頁都有的一個通用結構,它們記錄了頁的一些通用狀態資訊,和Checksum用來驗證頁的完整性。Page Header是索引頁特有的結構,它記錄了頁內使用者記錄相關的狀態資訊。User Records部分用來存放使用者記錄。另外,由於頁內的記錄數量也不少,為了提高頁內記錄的檢索效率,InnoDB在索引頁中加入了Page Directory,它通過將記錄分組,將組裡最大的記錄的地址偏移量形成一個個槽,Page Directory就是由這些槽構成的。檢索資料時,使用二分法快速定位到槽所在的組,就可以避免遍歷所有組的記錄了。
到此這篇關於MySQL索引頁結構的文章就介紹到這了,更多相關MySQL索引頁結構內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45