MySQL系列:innodb源碼分析之資料表空間管理,mysqlinnodb

來源:互聯網
上載者:User

MySQL系列:innodb源碼分析之資料表空間管理,mysqlinnodb

innodb在實現資料表空間(table space)基於檔案IO之上構建的一層邏輯儲存空間管理,table space採用邏輯分層的結構:space、segment inode、extent和page.在實現層的邏輯使用了磁碟鏈表這種結構來管理邏輯關係。我們先來介紹磁碟鏈表。

1.磁碟鏈表磁碟鏈表的實現fut0lst.*檔案當中, innodb為了管理資料表空間和索引模組,定義了一個基於磁碟的鏈表,主要是用來儲存磁碟資料結構之間的關係。這個鏈表不是基於記憶體指標的,而是基於page no和boffset來做位置綁定的。在innodb中定義了一個fil_addr_t的結構來做描述:
typedef struct fil_addr_struct{ ulintpage;        /*page在space中的編號*/ ulintboffset;     /*page中的位元組位移量,在記憶體中使用2位元組表示*/}fil_addr_t;
fil_addr_t可以通過fut_get_ptr函數來獲得對應node的記憶體位置(flst_node_t)
flst_node_t可以通過buf_ptr_get_fsp_addr來確定fil_addr_t。flst_node_t中存有12個位元組的內容,前6個位元組(page:4 boffset:2)表示相對自己前一個node的fil_addr_t資訊,後6個位元組表示相對自己後1個node的fil_addr_t。除了flst_node_t以外,磁碟鏈表還有一個頭資訊flst_base_node_t,頭資訊是一個節點個數FLST_LEN(4位元組) + FLST_FIRST (6位元組)+ FLST_LAST(6位元組).1.1磁碟鏈表的結構關係

2.space結構分析 在innodb的資料表空間中,所有的資料都是以page為單位來儲存的,在space(資料表空間)中有兩種page: FSP_HDR/XDES Page、fseg inodes Page。每個page是以預設16KB的大小儲存的,innodb在分配page的時候總以一個extent為單位一次性分配64個page。2.1 FSP HDR/XDES Page2.1.1XDES結構分析(extent)這個類型的page主要儲存兩類資訊,前面112個位元組儲存的是File Space header資訊,後面剩餘的空間儲存多個extent描述資訊(XDES ),具體儲存結構圖如下:


只有space的第一個page會儲存FSP header,其他的頁是用0填充的。 每個XDES Page最大包含256個XDES descritptors Entry,每個XDES descritptors Entry對應的是一個extent。XDES descritptors Entry的結構描述如下:

File Segment ID                 是當前extent所屬segment的ID
    XDES list                         是磁碟雙向鏈表的一個節點,分別指向前一個XDES entry的page位置和後一個                                              XDES entry的page位置
    state                                 extent的狀態, XDES_FREE、XDES_FREE_FRAG、XDES_FULL_FRAG、                                              XDES_FSEG,在為XDES_FSEG的時候,表示這個extent已經隸屬於一個                                              Segment,extent在建立的時候會指定成XDES_FSEG狀態。一個extent在剛                                              分配時的狀態XDES_FREE.
   bitmap                              當前extent的所有page的狀態索引,一個page佔用2 bit,第一個bit表示是否被使用                                             狀態,第二個位表示是否並 清空狀態,清空狀態暫時好像沒有用 到,都是TRUE。
2.1.2 FSP Header            space id                    當前資料表空間的ID            size                     當前space最大可容納的page數,檔案擴大時才會改變這個值
            limit                   當前space已經分配初始化的page數,包括閒置和已經使用的
            flag                     未起作用
            frage used         FSP_FREE_FRAG列表中已經被使用的page數
            free list               space中可用的extent對象列表,extent裡面沒有一個page被使用
            frag free list       有可用碎葉page的extent列表,exntent裡面有部分page被使用
            frag full list       沒有有可用page的extent列表,exntent裡面全部page被使用
            segment id         下一個可利用的segment id
            full inode list     space當前完全佔滿的segment inode頁列表
            free inode list     space當前完全佔滿的segment inode頁列表
2.2 Fseg inode Page這個頁類型是儲存fseg inode用的頁,每個inode 佔用192個位元組,一個page儲存有85個inode對象,結構如下:

 在FIL Header後面緊接了12個位元組,這個12個位元組其實就是full inode list或則free inode list中的列表所以,分別表示前後的fil_addr_t。每個inode資訊佔用192個位元組,裡面分別管理對應的extent和fragment page。inode 結構如下:
    fseg id                                    segment ID
            not full used                          FSEG_NOT_FULL列表中的page數
            FSEG_FREE                         inode中閒置extent列表
            FSEG_NOT_FULL               extent有部分page被佔用,有部分page閒置extent列表
            FSEG_FULL                          完全佔滿的extent的列表
            FSEG_MAGIC_N                  校正魔法字
            fragment array                       一個長度為32的零散page索引儲存的數組,如果這個資料滿了.主要的作用是                                                             節省空間的,例如在表剛建立時,不會分配一個完整的extent給表用,只會分配                                                             6個PAGE頁,這時候就需要用fragment array來管理。

3.space結構圖3.1space架構關係圖
3.2模組關係

4.space的inode、extent和page分配流程 innodb的space中,inode、extent和page之間的關係是環環相扣的,inode對應的是segment,extent對應的是區,page是頁,也是資料表空間的最小分配單位。一個page在MySQL中預設是16KB大小,一個extent管理64個page,大小為1M,而inode可以管理很多extent加32個frag page(碎頁)。frag page是為了節省空間的而定義的。在瞭解了以上基本的概念後,我們開始分析inode的分配、extent的分配和page的分配過程。

4.1 inode的分配流程通過inode page的介紹我們可以知道,inode資訊一定是儲存在inode page中的,在分配inode的時候,一定是從inode page中擷取閒置inode。如果沒有inode page可以使用,會先去在space的free list得到一個inode page(在函數fsp_alloc_seg_inode_page),然後再在這個inode page獲得閒置inode。在這個過程中會涉及到兩個磁碟鏈表:FSP_SEG_INODES_FREE和FSP_SEG_INODES_FULL,這兩個隊列是管理inode page的,如果沒有空閑inode的inode page是放在FSP_SEG_INODES_FULL中的,如果還有空閑inode的inode page是放在FSP_SEG_INODES_FREE中。一個inode頁包含85個inode資訊。以下是inode 分配:


    第1步:在FSP_SEG_INODES_FREE為空白時,向space預設的頭頁中擷取一個inode page,對應函數fsp_alloc_seg_inode_page
    第2步:在申請inode時,如果FSP_SEG_INODES_FREE有可以的inode page,從inode page或的一個inode,對應函數fsp_alloc_seg_inode
    第3步:如果在申請inode後,inode所處的inode page已經沒有閒置inode了,會將這個inode page放入FSP_SEG_INODE_FULL,並將其從FSP_SEG_INODES_FREE中刪除。
    第4步:如果inode管理的所有的頁都是空閑,那麼這個inode狀態會被置為空白閑狀態,這個時候會將這個inode page從FSP_SEG_INODE_FULL移 到FSP_SEG_INODES_FREE中;這個過程只有在segment刪除的時候才會調用。對應的函數fsp_free_seg_inode

4.2extent的分配流程 extent的分配方式有兩種,一種是通過inode進行申請分配,一種是通過fragment片段方式申請分配。inode分配方式是當inode中沒有空閑可用的extent的時候,會向space free list中申請1個或者5個extent進行管理,如果當inode管理的extent數量小於40時,每次只會申請1個extent,如果超過這個大小,就會一次申請5個extent,這個過程會涉及到inode的FSEG_FREE、FSEG_NOT_FULL和FSEG_FULL三個磁碟鏈表。第二種申請方式是分配frag page時,是直接對extent進行申請,這其中會涉及到FSP_FREE_FRAG和FSP_FULL_FRAG這兩個磁碟鏈表。以下是分配:



中,1~7是屬於inode申請分配流程, 8~12是屬於frag page的申請extent方式
    1: 當inode的free list為空白,如果需要使用申請使用新的extent,innodb會從space free list獲得閒置extent加入到inode free list當中。
    2: 當inode  free list中有extent,如果申請使用新的extent,只只需要從inode free list中拿取,並將extent移到inode not full當中。
    3:只是通過inode方式申請頁的一個操作,這個時候extent有足夠多的空閑page.
    4: 當extent中沒有閒置page時,會將這個extent從inode not full中轉移到inode full當中。
    5: 當一個page釋放時,這個page所處的extent是一個完全佔用的且被inode管理的extent,那麼page釋放後,就會將這個extent從inode full移到inode not full
    6:當一個page釋放時,這個page所處的extent有且只有這一個page被佔用,那麼page釋放後,這個extent就會歸還給inode list.並且會直接進行 7將extent歸還給space free list.
    8~12和以上步驟類似

4.3page的分配流程page的申請分配是基於inode 申請和extent申請的基礎上,頁的申請有外部通過inode方式申請,也有通過fragment page方式申請。fragment方式申請相對比較簡單,就不在表述,源碼中很清晰。inode方式分配是比較複雜的,其主要實現是在fseg_alloc_free_page_low和fseg_free_page_low這兩個函數。在fseg_alloc_free_page_low函數中實現了7種情況獲得inode中的page.
    1. 指定的inode的hint位置的頁是空閑狀態,直接返回對應的page
    2.descr是空閑狀態,但segment inode中的空閑page數量 < 1/8,且片段頁被全部用完,為其分配一個extent,並獲得hint對應的page
    3.如果descr不是空閑狀態,且segment inode中的空閑page數量 < 1/8,在inode當中獲得一個閒置extent,並且將這個extent descr對應的頁返回。
    4.descr是XDES_FSEG狀態,且這個extent中還有空閑page,從其中擷取一個page.
    5.除了以上情況外,如果descr不是閒置,但是inode還有其他的空閑extent,從其他的extent獲得一個空閑。
    6.如果其他的extent沒有空閑頁,但是fragment array還有閒置片段page,從閒置片段page中獲得一個空閑頁。
    7.如果連碎頁也沒有,直接申請分配一個新的extent,並在其中擷取一個閒置page.

5.綜述table space的實現在fsp0fsp.*檔案當中,也依賴於page0page.*  fil0fil.* 等檔案。innodb在儲存上,定義了最小的儲存單位就是page,space在設計這些層關係,都是為了更為高效和合理的管理page。space可以和其他表存在同一個資料庫檔案中,也可以一張表一個檔案儲存體。這取決於MySQL的配置。分析space的結構和工作原理有利於我們理解innodb的儲存方式,其後面理解索引、鎖和事務提供有力的基礎。上面也說到最小的儲存單位是page,我將在下一章節中單獨來介紹資料page的儲存方式和其工作原理。



相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.