综述
从上层的角度来看,InnoDB层的文件,除了redo日志外,基本上具有相当统一的结构,都是固定block大小,普遍使用的btree结构来管理数据。只是针对不同的block的应用场景会分配不同的页类型。通常默认情况下,每个block的大小为 UNIV_PAGE_SIZE,在不做任何配置时值为16kb,你还可以选择在安装实例时指定一个块的block大小。对于压缩表,可以在建表时指定block size,但在内存中表现的解压页依旧为统一的页大小。
从物理文件的分类来看,有日志文件、主系统表空间文件ibdata、undo tablespace文件、临时表空间文件、用户表空间。
由于数据库需要保证数据的完整性,因此在OS系统上封装了自己的文件系统。我们来看一张图,这样也能更好的理解innodb数据库的文件结构
首先看一下页(page)的结构
之前有说过,一个表空间文件都是由一个一个16kb的页组成,每个页都有一个32位序号(page number),通常称为偏移量,即离表空间初始位置的偏移量.因为每个页大小为16kb,所以第0个页的偏移量为0,第一个页的偏移量为16384等等.因为32位的最大值为2^32,所以一个表空间的最大值为2^32*16kb=64TB.
- Checksum为校验和,和磁盘打交道的程序为了保证数据正确性,都必须使用校验和,目的是验证因为磁盘空间损坏导致数据损坏;
- offset(Page Number)为页的序号,即偏移量;
- Previous Page和Next Page InnoDB的数据在内存缓冲区是由B+树组织的,而B+树中的每一层的页是由双向链表串起来,因为每个页header有指向上一个和下一个页的指针;这种结构可以提升全表扫描的效率;
- LSN for last page modification LSN如果不懂,可以查看InnoDB存储引擎这本书,简单说就是用于表示刷新到重做日志数据量,可用于重做日志恢复数据库.
- Page Type 即页的类型,页的类型决定了这个页其他部分存储的数据,常见的页类型有数据业,undo页,系统页等等;
- space id 即这个页属于的表空间
- flush LSN 这个值存储了刷新到整个系统任何页的最大LSN值.
接下来我们来看一下表空间(Tablespace)的一些基础知识
表空间是分段管理的,假如有一个表只有一个主键索引,那么这个表就有两个段,一个是内部节点段,即非叶子节点段,还有一个是叶子段,即存储数据的节点.如果一个表除了主键索引,还有一个辅助索引,那么这个这个表空间有四个段,主键内部节点段,主键叶子节点段,辅助索引内部节点段,辅助索引叶子节点段.InnoDB存储引擎有有一张图很好展示了段,区,页的关系:
当然共享表空间ibdata和用户表空间是不一样的,因为它需要存储更多全局的一些信息,例如doublewrite,undo等等,所以共享表空间拥有更多的段,这里先分析用户表空间.
每个表空间都有一个唯一space id,因为很多地方都需要使用到这个id,例如内存数据刷到磁盘时,需要使用这个space id来寻找表空间文件.InnoDB总有一个"系统空间",即共享表空间,这个表系统表空间的space id始终为0.
表空间结构
一个表空间文件是由一系列的页组成的,页数量最多可达2^32个.为了更好管理页,页又按1MB(64个连续的页)分为组,这个组称为区,InnoDB一般情况下是按区来给段分配空间.
为了管理表空间所有页,区以及表空间自己,Innodb必须使用一些数据结构来跟踪保存页区等信息,下图展示了一个表空间的示意图:
每一个表空间的第一个页为FSP_HDR(file space header)页,这个页保存了FSP header结构,这个结构保存了这个表空间的大小,以及完全没有被使用的extents,fragment的使用情况,以及inode使用情况等等,接下来详细介绍.
第1个页只能保存256个extents,也就是16384个页,256MB.因此每隔16384个页必须分配一个新的页来保存接下来的16384个页的信息,这个页就是XDES页,这个XDES页和第1个页除了FSP_HDR结构置0外(因为第一个page已经包含了base list,所以后面的XDES page 的FSP_HDR结构置0),其他都一样.
第二个页IBUF_BITMAP这个页就是插入缓存bitmap页,用于记录插入缓冲区的一些信息.
第三个页是inode页,该页用一个链表存储表空间中所有段(file segments);之前说段是由若干个extents组成,其实段除了extents之外,还有32个单独分配的"碎片"页组成,因为有些段可能用不到一个区,所以这里主要是为了节省空间.
FSP_HDR PAGE
数据文件的第一个Page类型为FIL_PAGE_TYPE_FSP_HDR
,在创建一个新的表空间时进行初始化(fsp_header_init
),该page同时用于跟踪随后的256个Extent(约256MB文件大小)的空间管理,所以每隔256MB就要创建一个类似的数据页,类型为FIL_PAGE_TYPE_XDES
,XDES Page除了文件头部外,其他都和FSP_HDR
页具有相同的数据结构,可以称之为Extent描述页,每个Extent占用40个字节,一个XDES Page最多描述256个Extent。