1. 程式人生 > >M有SQL數據庫Innodb儲存引擎----儲存頁的結構

M有SQL數據庫Innodb儲存引擎----儲存頁的結構

當前頁 eight spa ESS user fsp 方便 com 技術分享

上一篇博客回顧:

    1:數據庫擁有眾多的儲存引擎,現在主要使用的是Inoodb,這個儲存引擎有Compact,Redundant,Dynamic,Compressed四種行格式

    2:Compact行格式的結構分為變長數據長度列表,NULL值列表,記錄頭信息,真是數據儲存

    3:變長數據長度列表儲存的是變長數據類型數據的字節數逆順序,空值列不儲存,NULL值列表儲存非主鍵和沒有被NOT NULL 修飾的列,二進制位逆順序進行儲存。

    4:記錄頭信息包括了偏移量,槽數量,本組數據量,是否被刪除,數據類型,是不是B+樹子節點等等信息。

    5:真實數據會有三個三個虛擬列,ROW_ID(沒有主鍵的時候自動生成),ROLL_POINTER,TRANSACTION_ID(事務管理ID)

    5:行溢出數據的處理Compact行格式是使用最後記錄下一頁地址的方式,然而Redundant和Compressed是采用整頁記錄數據頁地址的方式,後兩者的Compressed采用壓縮算法。

    6:對於char相似類型的數據來說,如果我們采用可變的字符集進行操作也是會在可變長度數據列表裏面進行儲存的。

    7:對於可變數據長度列表儲存的占用字節為1或者2,NULL值用二進制位,記錄頭信息在Compact行格式占用5個字節,Redundant占用6字節。一頁空間16kb。

頁儲存結構:

    我們都知道的是數據庫一個頁的儲存空間是16kb,那麽這16kb的儲存空間是怎麽進行分配,數據在這個儲存空間裏是怎麽樣的一個格式呢?對於這些數據數據庫都進行了什麽操作?這就是我們今天需要進行學習的內容。

    技術分享圖片

    可能按照順序來說的話不是太方便進行講訴,而且看起來可能也不會效果太好,所以我們一點一點根據功能的劃分進行區分。

    User Records:

      這個區域對我們插入的數據進行保存,需要說明的是原本這一塊是不存在的,當我們插入數據的時候這塊區域才會被劃分出來。並且是從Free Space進行的劃分。當我們的Free Space區域所有的空間都變成了UserRecords,那麽這時候就是需要重新開辟一個儲存頁的時間了。

      那麽當我們把數據放在這個區域裏面的時候,是不是就是說沒有一點規則,隨便進行擺放,其實想一想就知道了,當我們數據過於龐大的時候,我們隨便擺放,查找會是多麽的痛苦。所以接下來在我們知道數據保存在那個位置以後我們需要弄清楚的是數據在User Records裏的情況。在這裏我們假設插入了四條我們自己的記錄:

      兩個虛擬的數據:我們可以看到下圖所示,我們插入了四條記錄的時候,但是在我們這個頁中存在的是六條記錄,也就是兩條我們說的每個頁中都會存在的虛擬記錄:最大記錄和最小記錄。他們都存infumum_supremum裏面,因為不是我們自己插入的記錄所以是不在User_Record裏面.最小記錄默認在開始,最大記錄在最末尾結束  

        技術分享圖片

      接下來我們再根據這六條記錄描述一些問題:

          1:我們在每條數據的記錄頭裏面提到的Record_Type標記的是這條數據的類型,當時我們說的是有0普通數據,1葉子節點數據,2最小數據,3最大數據。我們可以看到的是上邊最大和          最小數據分別是3和2, 我們自己插入數據的記錄頭信息在Record_type這裏都是0.

          2:我們在記錄頭信息裏面還可以看到的是delete_mask這個數據,表示的是數據是否被刪除,0表示沒有,1表示已經被刪除,所以上邊的數據都是0

          3:heap_no我們講過是標記該數據在頁中的位置,我們可以看到插入數據分別是2,3,4,5。那麽0和1去哪了,別著急,請看看最小記錄和最大記錄的該數據,是不是分別為0和1。我          們插入的數據都會從2開始計數,虛擬數據會占用默認的0和1的位置。

          4:插入數據的排列是否就是數據插入的順序,那顯然是不可能的,你沒想錯,數據會根據大小進行排列,那麽數據用什麽進行大小的排列?顯然就是主鍵進行比較。

          5:next_record記錄的就是相對於本條數據,下一條數據的地址偏移量,就是通過這條數據往下查找這麽多字節就可以找到下一條數據,沒錯。他就是使用的鏈表進行鏈接的。如下圖:

          技術分享圖片

          6:如果一條數據被刪除,也就是它的delete_mask被標記為了1,那麽這個會怎麽進行改變?就是和鏈表一致,進行鏈接的切斷就可以了。

             技術分享圖片

          7:我們在進行數據查找的時候就是這麽一條接一條的進行查找麽?從最小記錄開始根據next_record查找?那必然是耗時的一個活,顯然是不可能的,所以在就出現了分組這個概念。

            技術分享圖片

          技術分享圖片

          

        分組:

          我們可以看到的是六條數據分成了兩組,首先是最小的虛擬數據獨自一組,然後剩下的五個數據再分成一組。在這裏需要知道的就是MySql數據庫在每個頁中進行數據分組的時候默認的        最小數據是第一組,它擁有一條數據,就是最小數據,不能在插入其他數據。最大數據是第二組,我們在進行數據插入的時候都是先插入最大數據組,當最大數據組滿足的時候進行分裂,形        成普通的分組,然後再進來的數據又插入最大數據組,如此循環往復,完成數據的分組。

        槽:

          我們還可以看到的是在分組的圖裏面出現了兩個奇奇怪怪的東西,槽,我們上一篇文章頁訴說過這個玩意兒。每個分組數據的相對於頁的地址偏移量就是一個槽數據,一個分組有一個         槽,槽存在的位置就是頁信息的Page Directory。在這裏我需要強調的是在記錄頭信息中有個地址偏移量next_record,這個偏移量是本條數據相對於下一條數據位置,然後槽中的偏移量是分        組最後一條數據相對於頁的偏移量。

        尋找:

          有了分組以後,我們在進行數據查找的時候就是根據二分法確定對應數據所在的槽位置,然後在使用記錄頭信息的next_record一條條進行查找。

        n_owned:

          這個數據我們在記錄頭信息中一直看到,其實在這裏就可以結束這個數據了。它表示的是該分組有多少條數據,存在於分組的最後一條信息中。我們可以看到的是每個分組的前面的數據        n_owned都是0,只有在最後一條數據上它才有值。

page_header

  上邊我們通過數據的方式介紹了User_Records,infumum_supremum,page_directory,Free spce這四塊空間的使用情況,接下來需要進行解釋的就是page_header,file_header,file tailer這三塊空間。

   首先說的就是page_header,這個地方儲存的就是數據的一些信息:

    

PAGE_N_DIR_SLOTS 2字節 在頁目錄中的槽數量
PAGE_HEAP_TOP 2字節 第一個記錄的地址
PAGE_N_HEAP 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,該值僅在二級索引中定義
PAGE_LEVEL 2字節 當前頁在索引樹中的位置,高度
PAGE_INDEX_ID 8字節 索引ID,表示當前頁屬於哪個索引
PAGE_BTR 10字節 非葉節點所在段的segment header,僅在B+樹的Root頁定義
PAGE_LEVEL 10字節 B+樹所在段的segment header,僅在B+樹的Root頁定義

      在上邊我們需要說的就是PAGE_DIRECTION和PAGE_N_RECS這兩個數據第一個指的是最後插入的方向,相對於上一條數據來說,我們新插入的比他大,就在右邊,反之則在左邊,這就是方        向。當我們插入數據連續的都在右邊或者是都在左邊的時候就會記錄下數量。當然如果改變方向的話這個數據會被清空從零開始計數。

File_Header:

  上邊講的page_header就是對頁儲存記錄的描述,那麽這裏的File_Header就是對頁信息的描述:

   

名稱占用空間大小描述
FIL_PAGE_SPACE_OR_CHKSUM 4字節 頁的校驗和(checksum值)
FIL_PAGE_OFFSET 4字節 頁號
FIL_PAGE_PREV 4字節 上一個頁的頁號
FIL_PAGE_NEXT 4字節 下一個頁的頁號
FIL_PAGE_LSN 8字節 最後被修改的日誌序列位置(英文名是:Log Sequence Number)
FIL_PAGE_TYPE 2字節 該頁的類型
FIL_PAGE_FILE_FLUSH_LSN 8字節 僅在系統表空間的一個頁中定義,代表文件至少被更新到了該LSN值,獨立表空間中都是0
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 4字節 頁屬於哪個表空間

  我們可以看到三個值,一個記錄的是這個頁的頁號,上一個頁,下一個頁。針對上面我們講的一個頁中的數據是采用單向鏈表的形式進行連接,那麽我們可以想到的是數據庫中的頁是采用的雙向鏈表。

    技術分享圖片

   我們在上面還可以看到的是 FIL_PAGE_TYPE這個值,描述的是這個頁的類型,顯然我們數據庫不可能就只有一種數據頁,上面我們講的儲存真實數據頁就是數據頁。FIL_PAGE_INDEX,也就是我們提到的   B+樹葉子節點。

   

名稱十六進制描述
FIL_PAGE_ALLOCATED 0x0000 最新分配,還沒使用
FIL_PAGE_UNDO_LOG 0x0002 Undo Log頁
FIL_PAGE_INODE 0x0003 段信息的節點
FIL_PAGE_IBUUF_FRE_LIST 0x0004 Insert Buffer空閑列表
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頁
FIL_PAGE_INDEX 0x45BF B+樹的子節點

 

File Trailer

  這玩意需要和上面File header中的FIL_PAGE_SPACE_OR_CHKSUM這個屬性系統校驗和一起說。我們都知道的是頁是一塊16kb的儲存空間,不管是內存刷新到數據庫取用都是一次操作16kb。那麽如果在中途產生停電等不可抗拒的因素,這時候這裏就起作用了。File Header位於頁的開始,它會計算一個校驗和,這個校驗和你可以這麽理解,當我們需要一個很復雜的字符串的時候,往往會將它按照一定的算法進行計算出一個整數值,當和其它字符串進行比較的時候就用這個值。所以校驗和也是這個道理,File Trailer是位於頁尾部的,他也會儲存一個校驗和。如果數據不完整,那麽兩個校驗和不可能一致,那麽就可以判定這個數據頁是損壞的。

       

      

M有SQL數據庫Innodb儲存引擎----儲存頁的結構