Data Organization in InnoDB

翻译一篇Transactions on InnoDB的文章


Data Organization in InnoDB

Introduction

这篇文章将会介绍在InnoDB引擎中数据是怎么组织的。首先我们会了解InnoDB创建的不同的文件,然后了解下逻辑文件的组织,比如tablespaces,pages,segments和extents。我们会逐个详细地解释每个文件并且讨论他们之间的关系。文章的最后,读者将会对InnoDB存储引擎内部数据布局有一个高层次的理解。

The Files

MySQL会把所有数据存在data目录中。data目录可以由命令行选项(-data-dir)指定,或者在配置文件中(datadir)指定。详细请参考Server Command Options

默认情况下,当InnoDB初始化时,它会在data目录中创建三个重要的文件-----ibdata1, ib_logfile0, ib_logfile1。系统和用户数据存储在ibdata1(又叫data file)中,ib_logfile0,ib_logfile1是redo log files。这三个文件的位置和大小都可以配置。参考Configuring InnoDB

这个data file ibdata1属于system tablespace,tablespace id(space_id)为0。system tablespace可以包含多于一个data file。所有其他的tablespaces只能包含一个data file。并且,只有system tablespace能包含多于一个table,其他tablespaces只能包含一个table。

data files 和 redo log files 在内存中由C的结构体fil_node_t表示

Tablespaces

默认情况下,InnoDB只包含一个tablespace:system tablespace,id为0。使用innodb_file_per_table参数可以间接地创建更多的tablespaces。在MySQL5.6中,这个参数默认为ON。当处于ON时,每个table将会在自己的tablespace中创建,并且是一个独立的data file。

tablespace 和 data files 的关系在InnoDB的源代码注释中有(storage/innobase/fil/fil0fil.cc):

A tablespace consists of a chain of files. The size of the files does not have to be divisible by the database block size, because we may just leave the last incomplete block unused. When a new file is appended to the tablespace, the maximum size of the file is also specified. At the moment, we think that it is best to extend the file to its maximum size already at the creation of the file, because then we can avoid dynamically extending the file when more space is needed for the tablespace.”

最后一句话关于避免动态扩展的情况只适用于redo log files而不适用于data files。Data files是动态扩展的,但是redo log是pre-allocated的。并且,前面说过,只有system tablespace可以有超过一个data file。

注释也清楚的提到即使tablespace可以有多个files,他们也被看成连接成的单独一个大的文件。所以,tablespace里的files次序很重要。

Pages

一个data file被逻辑的分割成等大小的pages。第一个data file的第一个page的page number被标识为0,下一个为1等如此继续。一个tablespace里的一个page唯一的被page_no标识。并且每个tablespace被space_id唯一标识。所以一个page可以由(space_id,page_no)在InnoDB中被唯一标识。进一步的,InnoDB中的任意位置可以由( space_id,page_no,page_offset)标识,page_offset是page中的字节数的偏移。

不同的data files的pages的关系在另一段源码注释中有:“A block's position in the tablespace is specified with a 32-bit unsigned integer. The files in the chain are thought to be catenated, and the block corresponding to an address n is the nth block in the catenated file (where the first block is named the 0th block, and the incomplete block fragments at the end of files are not taken into account). A tablespace can be extended by appending a new file at the end of the chain.”意思是所有的data files的第一个page不会全都为0,只有tablespace里的第一个data file的第一个page才会有page_no为0。

上面的注释中也提到page_no是一个32位的无符号整型。这是page_no存到disk中的大小。

每个page都有一个page header(page_header_t)。具体请参考Jeremy Cole's blog The basics of InnoDB space file layout


Extents

一个extent是一个1M大小的连续pages。extent的大小由下定义 (1048576 bytes = 1MB):

#define FSP_EXTENT_SIZE (1048576U / UNIV_PAGE_SIZE)

UNIV_PAGE_SIZE是一个编译时常量。从mysql-5.6以后,它是一个全局变量。extent中的page个数由page大小决定。如果page大小为16K(默认),extent将有64个pages。(对于大的数据段,InnoDB存储引擎最多每次可以申请4个区,以保证数据的顺序性能,来自《MySQL技术内幕》)


Page Types

page可以有不同的用途。page type就是用来标识page的不同用途。page type存于page header中。page types可以在头文件中查看: storage/innobase/include/fil0fil.h,下面为page type列表:

Page Type

Description

FIL_PAGE_INDEX

The page is a B-tree node

FIL_PAGE_UNDO_LOG

The page stores undo logs

FIL_PAGE_INODE

contains an array of fseg_inode_t objects.

FIL_PAGE_IBUF_FREE_LIST

The page is in the free list of insert buffer or change buffer.

FIL_PAGE_TYPE_ALLOCATED

Freshly allocated page.

FIL_PAGE_IBUF_BITMAP

Insert buffer or change buffer bitmap

FIL_PAGE_TYPE_SYS

System page

FIL_PAGE_TYPE_TRX_SYS

Transaction system data

FIL_PAGE_TYPE_FSP_HDR

File space header

FIL_PAGE_TYPE_XDES

Extent Descriptor Page

FIL_PAGE_TYPE_BLOB

Uncompressed BLOB page

FIL_PAGE_TYPE_ZBLOB

First compressed BLOB page

FIL_PAGE_TYPE_ZBLOB2

Subsequent compressed BLOB page


每个page type有不同的用途。解释每个page type超过了本章的主题。目前为止,只需了解所有pages都有一个page header并且他们包含了page type,并且根据page type,page的内容和布局就能决定了。


Tablespace Header

每个tablespace都有一个fsp_header_t结构的头部。这个数据结构存在tablespace的第一个page中。

  • The table space identifier (space_id)

  • Current size of the table space in pages.

  • List of free extents

  • List of full extents not belonging to any segment.

  • List of partially full/free extents not belonging to any segment.

  • List of pages containing segment headers, where all the segment inode slots are reserved. (pages of type FIL_PAGE_INODE)

  • List of pages containing segment headers, where not all the segment inode slots are reserved. (pages of type FIL_PAGE_INODE).

InnoDB Tablespace Header Structure

从tablespace的header中,我们能获得可用的segments列表。宏定义FSP_HEADER_SIZE定义了header的大小,大小为16*7=112 bytes。


Reserved Pages of Tablespace

前面提到过,InnoDB总会有一个space_id为0的system tablespace。这个特别的tablespace只要MySQL在运行就一直保持打开。这个tablespace的前几个pages保留作为内部使用。这些信息可以从头文件 storage/innobase/include/fsp0types.h中获得。下面列出的是几个pages的简单介绍。

Page Number

The Page Name

Description

0

FSP_XDES_OFFSET

The extent descriptor page.

1

FSP_IBUF_BITMAP_OFFSET

The insert buffer bitmap page.

2

FSP_FIRST_INODE_PAGE_NO

The first inode page number.

3

FSP_IBUF_HEADER_PAGE_NO

Insert buffer header page in system tablespace.

4

FSP_IBUF_TREE_ROOT_PAGE_NO

Insert buffer B-tree root page in system tablespace.

5

FSP_TRX_SYS_PAGE_NO

Transaction system header in system tablespace.

6

FSP_FIRST_RSEG_PAGE_NO

First rollback segment page, in system tablespace.

7

FSP_DICT_HDR_PAGE_NO

Data dictionary header page in system tablespace.



从上面可以知道,任何一个tablespace都有前三个pages。但是后面五个pages只有在system tablespace中被保留。其他的tablespace只有后面三个被保留。

当innodb_file_per_table选项启用时,对每个table都会创建一个独立的tablespace,里面有个data file。源代码中函数dict_build_table_def_step()的注释描述如下:

               /* We create a new single-table tablespace for the table. 
                We initially let it be 4 pages: 
                - page 0 is the fsp header and an extent descriptor page, 
                - page 1 is an ibuf bitmap page, 
                - page 2 is the first inode page, 
                - page 3 will contain the root of the clustered index of the 
                table we create here. */ 

File Segments

一个tablespace可以包含多个segments。File segments(或者segments)是逻辑实体。每个segment有一个segment header(fseg_header_t),这个头指向inode(fseg_inode_t,描述file segment)。这个头包含如下信息:

  • The space to which the inode belongs

  • The page_no of the inode

  • The byte offset of the inode

  • The length of the file segment header (in bytes).

注意:如果fseg_header_t和fseg_inode_t对那些信息有合适的定义,那源码级别可读性更强。

fseg_inode_t结构包含如下信息:

  • The segment id to which it belongs.

  • List of full extents.

  • List of free extents of this segment.

  • List of partially full/free extents

  • Array of individual pages belonging to this segment. The size of this array is half an extent.

当一个segment需要增长时,他会从他的tablespace中获得可用的extents或者pages。


Table

在InnoDB中,当创建一个表时,内部会创建一个聚族索引 (B-tree)。这个B-tree包含了两个file segments,一个用于non-leaf pages另一个用于leaf pages。源码文档中:

In the root node of a B-tree there are two file segment headers. The leaf pages of a tree are allocated from one file segment, to make them consecutive on disk if possible. From the other file segment we allocate pages for the non-leaf levels of the tree.”

对于一个给定的table,B-tree的root page会从数据字典中获得。所以在InnoDB中,每个table存在于一个tablespace内,并且包含一个B-tree(聚集的索引,包含两个file segment)。每个file segment包含多个extents,每个extent包含连续pages组成的1M大小空间。


结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值