Chinaunix首页 | 论坛 | 博客
  • 博客访问: 27455
  • 博文数量: 3
  • 博客积分: 72
  • 博客等级: 民兵
  • 技术积分: 55
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-29 10:56
文章分类

全部博文(3)

文章存档

2012年(1)

2011年(2)

我的朋友

分类: Mysql/postgreSQL

2012-01-21 15:50:45

上一篇文章主要概述了下innodb page,extent,extent descriptor 等相关概念,本节将讨论下segment及space header等相关概念。

一. segment管理

1. segment inode概念

我们已经清楚innodb通过extent来管理一组物理文件空间上连续的page,而innodb通常需要管理大量这样的extent,比如innodb的btree存储需要占用大量的extent,所以需要有一个单位用来管理extent,这个单位就是segment,实际一颗btree就由2个segment组成,一个用来管理所有非叶节点,一个用来管理页节点,实际在innodb中通过一个叫segment inode的结构来存储segment相关的一些信息,也就是说每个segment都会对应有一个segment inode,我们看下它的定义:(fsp0fsp.c)

  1. #define FSEG_INODE_PAGE_NODE    FSEG_PAGE_DATA     
  2. //fil header后紧跟segment inode page文件链表域
  3. #define FSEG_ARR_OFFSET        (FSEG_PAGE_DATA + FLST_NODE_SIZE)  
  4. //segment inode存储开始位置
  5. /*-------------------------------------*/
  6. #define    FSEG_ID            0                                
  7. //segment inode所对应segment id
  8. #define FSEG_NOT_FULL_N_USED    8                              //半满extent链表使用数量
  9. #define    FSEG_FREE        12                                 //空闲extent链表
  10. #define    FSEG_NOT_FULL        (12 + FLST_BASE_NODE_SIZE)     //半满extent链表
  11. #define    FSEG_FULL        (12 + 2 * FLST_BASE_NODE_SIZE)     //全满extent链表
  12. #define    FSEG_MAGIC_N        (12 + 3 * FLST_BASE_NODE_SIZE)  //校验用magic数字
  13. #define    FSEG_FRAG_ARR        (16 + 3 * FLST_BASE_NODE_SIZE) //碎片页偏移地址
  14. #define FSEG_FRAG_ARR_N_SLOTS    (FSP_EXTENT_SIZE / 2)         //碎片页数量(32个)
  15. #define    FSEG_FRAG_SLOT_SIZE    4                            //管理碎片页占用大小
首先segment inode数据也是连续存放在一个page中,开始位置也是第38字节(FIL_HEADER之后),那么我们管这个专门用来存放segment inode的page 叫做segment inode page,其中主要存在3个用来管理extent的文件链表,以及32个碎片页的地址,FSEG_FULL,FSEG_NOT_FULL,FSEG_FREE是3个文件头指针,通过extent descriptor的XDES_FLST_NODE将extent挂在对应的segment上,这样一个segment就可以管理其所属的extent了。那么读到这里还有跟问题需要解释,有了segment inode但是我们如何得知一个segment对应的inode在哪里呢?换句话说需要有个地方存放segment inode的位置。

2. segment header概念

我们知道segment inode也是顺序存放在一个特殊的page中的,那么我们只要知道这个page所在的space id和page no以及这个inode在该page中的offset就可以定位到这个inode了,所以在innodb中有如下定义:(fsp0types.h)
  1. #define FSEG_HDR_SPACE        0    /*!< space id of the inode */
  2. #define FSEG_HDR_PAGE_NO    4    /*!< page number of the inode */
  3. #define FSEG_HDR_OFFSET        8    /*!< byte offset of the inode */

  4. #define FSEG_HEADER_SIZE    10    /*!< Length of the file system
  5.                     header, in bytes */
实际存放这些信息的结构我们就叫它segment header, 我们前面讨论过一颗btree会有2个segment,非叶节点一个,页子节点一个,实际btree的root节点对应的page里就存放着这2个segment的segment header,定义如下(page0page.h):
  1. #define PAGE_BTR_SEG_LEAF 36    /* file segment header for the leaf pages in
  2.                 a B-tree: defined only on the root page of a
  3.                 B-tree, but not in the root of an ibuf tree */

  4. #define PAGE_BTR_SEG_TOP (36 + FSEG_HEADER_SIZE)
  5.                 /* file segment header for the non-leaf pages
  6.                 in a B-tree: defined only on the root page of
  7.                 a B-tree, but not in the root of an ibuf
  8.                 tree */
这样通过访问btree的root节点我们很方便的能够找到所有节点对应的segment inode然后根据数据存储需要来分配和管理其对应的所有extent及page。
最后我们遗漏了一个最重要的结构没有讲 - space header:

二. Space Header 结构

虽然从前面的知识我们已经发现通过segment就可以把所有的page,extent等管理起来,但是实际上并不是所有的page都属于某个segment,比如用来存储segment信息的inode page本身就不是在segment内被分的,innodb中会通过segment来保留足够的空闲extent给特殊的场景使用,比如btree和rollback segment,而其它很多场景并不是从某个segment中分配空闲page的。

无论是segment还是独立的extent本身都需要一个结构来统一管理它们,这个结构就是space header,它是整个innodb表空间管理中的总管,所有跟extent,page,segment分配管理有关的事情实际都先要通过它,我们看下具体结构:(fsp0fsp.c)
  1. #define FSP_SPACE_ID        0    /* space id */
  2. #define FSP_NOT_USED        4    /* this field contained a value up to
  3.                     which we know that the modifications
  4.                     in the database have been flushed to
  5.                     the file space; not used now */
  6. #define    FSP_SIZE        8    /* Current size of the space in
  7.                     pages */
  8. #define    FSP_FREE_LIMIT        12    /* Minimum page number for which the
  9.                     free list has not been initialized:
  10.                     the pages >= this limit are, by
  11.                     definition, free; note that in a
  12.                     single-table tablespace where size
  13.                     < 64 pages, this number is 64, i.e.,
  14.                     we have initialized the space
  15.                     about the first extent, but have not
  16.                     physically allocted those pages to the
  17.                     file */
  18. #define    FSP_SPACE_FLAGS        16    /* table->flags & ~DICT_TF_COMPACT */
  19. #define    FSP_FRAG_N_USED        20    /* number of used pages in the
  20.                     FSP_FREE_FRAG list */
  21. #define    FSP_FREE        24    /* list of free extents */
  22. #define    FSP_FREE_FRAG        (24 + FLST_BASE_NODE_SIZE)
  23.                     /* list of partially free extents not
  24.                     belonging to any segment */
  25. #define    FSP_FULL_FRAG        (24 + 2 * FLST_BASE_NODE_SIZE)
  26.                     /* list of full extents not belonging
  27.                     to any segment */
  28. #define FSP_SEG_ID        (24 + 3 * FLST_BASE_NODE_SIZE)
  29.                     /* 8 bytes which give the first unused
  30.                     segment id */
  31. #define FSP_SEG_INODES_FULL    (32 + 3 * FLST_BASE_NODE_SIZE)
  32.                     /* list of pages containing segment
  33.                     headers, where all the segment inode
  34.                     slots are reserved */
  35. #define FSP_SEG_INODES_FREE    (32 + 4 * FLST_BASE_NODE_SIZE)
大部分可以通过注释看懂,这里重点说明如下:
1. space header是在每一个extent descriptor page中存在,但只有第一个是使用的,其余只占用空间但不使用,也就是说space header存放在page 0中第38个字节后。

2. space header有3个文件链表头,FSP_FREE,FSP_FREE_FRAG,FSP_FULL_FRAG将所有不属于某个segment的extent链接在一起,也是通过extent descriptor的XDES_FLST_NODE域,分别代表空闲链表,半空闲链表,满链表。

3. space header中有2个链表头,将所有segment inode page链接在一起,通过segment inode page 的FSEG_INODE_PAGE_NODE节点域链接在一起,分别代表空闲inode page和满inode page链表。

比如innodb要创建一个segment并保留部分extent,那么它首先从space header中的FSP_FREE中拿走对应需要的extent,并把它挂到segment的FSEG_FREE链表上。而对应某些其它的page分配则可以直接通过space header的对应链表找到空闲的extent,再通过extent descriptor page找到对应空闲的page。

到这里整个表空间的基础数据结构就都讲完了,其它相关代码可以翻阅fsp0fsp.c查看
阅读(3074) | 评论(0) | 转发(0) |
0

上一篇:understanding innodb internal - 表空间管理1

下一篇:没有了

给主人留下些什么吧!~~