浅析innoDB数据存储结构

浅析innoDB数据存储结构

No.1

引言

 

InnoDB是我们日常开发中最常使用的Mysql存储引擎,对于这个“老朋友”,你知道他是如何存储数据记录的吗,你知道他是如何建立索引的吗?本文将会和大家一起深入理解下innoDB数据存储结构,讲讲逻辑上的存储结构和“页”的数据结构,让你做innoDB的真兄弟!

 

 

No.2

InnoDB体系结构

 

由图可知,Mysql数据库可简单理解为3部分

  • 操作文件(数据)的后台线程

  • 减少cpu与磁盘速度差异的内存池

  • 存储索引,数据等信息的文件集合

而本文要介绍的innoDB存储结构实质上就是指innoDB在存储文件这一部分的数据结构。

数据库文件中需要存储哪些数据?

  • 数据

  • 索引

  • 表结构

  • 日志:包括错误日志,慢查询日志,查询日志,

    二进制日志,undo,redo

  • 其他

 

数据库文件物理分布

在具体讲解逻辑存储结构前,我们先简单了解下物理上这些文件是怎么分布的。物理分布如下图所示。

 

  • .frm文件

    此类型文件用于存储表结构,此结构与使用引擎无关,每张表都存此文件。特别的是当创建一个视图时,也会生成此类新文件用于记录视图的定义。

  • .ibd文件

    此类型文件为表空间

    • innoDB默认情况下会存在一个10M大小的表空间ibdata1,innoDB管理的表的数据都会存储在此表空间中

    • 可以通过设置innodb_data_file_path来指定多个文件组成一个表空间,若多个文件不在同一个磁盘下,则可以平均磁盘的负载,提升性能。

    • 可以通过设置innodb_file_per_table来设置每个表生成单独的ibd表空间,这样数据就不会存在默认的表空间下了。

特别注意:此处大家可能无法理解表空间是个什么概念,大家先记住.ibd存储是表空间文件即可,后面会进行讲解。

 

 

No.3

innoDB逻辑存储结构

 

数据都被逻辑的放到一个空间里,称之为表空间(tablespace),表空间又由段(segment)、区(extent)、页(page)组成 ,页innoDB文件管理的最小单位。

  • 一个段256M (不可变)

  • 一个区1M (不可变)

  • 一个页16K (可变)

  • 一个段=256区=256*64个页

表空间结构

由上图可知,表空间是处于结构的最外层。所有的数据都存放在表空间中,文件格式为.ibd。

特别注意的是,如果我们设置了每个表对应一个表空间,那共享的表空间是不是就没有用了呢?

答案是否定的,对于每个表独立的表空间来说只存数据、索引、插入缓冲Bitmap页,其他如回滚信息、系统事务信息等还在共享表空间中。

 

Segment-段

表空间由各个段组成,常见的段有数据段、索引段、回滚段等 

数据段即叶子节点 

索引段即非叶子节点

Extend-区

区是由连续的页组成的空间,在任何情况下每个区的大小都是1M,默认情况下每个页的大小是16KB,即一个区有64个页。

Page-页

页是InnoDB磁盘管理的最小单元,默认每页16KB,可通过innodb_page_size设置大小为4K,8K,16K,但设置完成后不可更改。

常见页类型:

数据页 , undo页,系统页,事务数据页,插入缓冲位图页

插入缓冲空闲列表页,未压缩的二进制大对象页,压缩的二进制大对象页

 

段-区-页组织结构

对于一个表空间来说至少会有个0号页面(FSP_HDR)用于存储extend相关的信息,记录了哪些空闲,哪些满,哪些有碎片等信息,对于一个FSP_HDR页来讲,只能维护256个extend信息,所以每隔256M就会有一个XDES用来维护下面的区的信息。那为什么是256个区呢?下图分别给出了FSP(XDES)和 XDES entry的结构。

 

由上图可知,每个区对应40byte的记录,那16kb扣除其他信息,可存256条记录,所以一个FSP/XDES页可存256个区信息,同时也就导致了每个256M就需要有一个XDES页。

总结一下

综上所诉,一个表空间有很多页,为了更高效对页进行管理呢,每64个页划分为一组就是区,每256个区再划分为一个段,我个人认为区和段并不是真实存在的,只是一个逻辑概念。

 

 

No.4

INNODB数据页结构

 

通过上文相信大家对innoDB的数据结构已经有了一个整体上概念,也应该知道了页是innoDB存储引擎能操作的最小磁盘单位,页类型是B-tree的页存放的即是表中行的实际数据,下面我们继续深入了解数据页的结构。

组成部分

其中File Header 和 PageHeader 和 Infimun + SupremumRecords,File Trailer是大小固定的用于存储页的一些相关信息,其余的是和数据相关的则为不定长。

File Header

名称 

大小(字节) 

说明 

FIL_PAGE_SPACE_OR_CHECKSUM 

代表了页的checksum值 

FIL_PAGE_OFFSET 

表空间中页的偏移值 

FIL_PAGE_PREV   

当前页的上一个页 

FIL_PAGE_NEXT   

当前页的下一个页 

FIL_PAGE_TYPE   

页类型 

FIL_PAGE_LSN 

该值代表了该页最后被修改的日志序列位置 

FIL_PAGE_FILE_FLUSH_LSN 

该值仅在系统表空间定义,独立表空间为0 

FIL_PAGE_ARCH_LOG_NO_SPACE_ID 

页所属表空间 

页在逻辑上是连续的,在磁盘中并不是连续的,而是通过上下指针进行逻辑关联,构成双向链表。但是页内的物理地址是连续的,页内的记录是乱序的单向链表。

Page Header

记录数据页的状态信息,14部分组成,共56字节

 

名称 

大小(字节) 

说明 

PAGE_N_DIR_SLOTS 

Page Directory的Solt数 

PAGE_HEAP_TOP 

指向空闲空间的起始地址 

PAGE_N_HEAP 

页记录数,包含已经标记删除的 

PAGE_FREE 

指向可重用空间的首指针 

PAGE_GARBAGE 

 已删除记录总数 

PAGE_LAST_INSERT 

最后插入记录位置 

PAGE_N_RECS  

页记录数,不包含已经标记删除的

 PAGE_LEVEL 

当前页在索引数的位置 

PAGE_INDEX_ID  

索引id,当前页属于哪个索引 

PAGE_BTR_SEG_LEAF  

10 

B+树root页定义,非页子节点所在段 

PAGE_BTR_SEG_TOP 

10 

B+树root页定义,非页子节点所在段 

todo 差表格

Infimun和SupremunRecords

虚拟的行记录,可认为是占位符,用来限定记录边界,Infimun记录是比该页主键值都要小的值,Supermun是比任何可能大的值还要大的值,两个记录在页创建时候创建 

UserRecords(行记录)

InnoDB存储引擎提供了Compact和Redundant两种格式来存放行记录数据。redundant是为了兼容之前版本而保留的我们不做过多研究,我们简单了解下Compact格式。

Compact格式 :compact行记录格式是从5.0引入,然后mysql5.1开始 Compact成为了默认的存储记录格式。

  • 可以通过SHOW TABLE STATUS LIKE 'table_name',查看当前使用的格式。

  • 可以使用CREATE TABLE 表名(列信息)ROW_FORMAT=COMPACT进行指定行格式。

  • 可以使用ALTER TABLE 表名 ROW_FORMAT = 行格式名称进行更改行格式

上图为Compact行记录格式。

变长字段长度列表:当列长度小于255时,用一个字节表示,当列长度>255时,用2个字节表示,由此也可以解释varchar的长度最长为65535 (2的16次幂),刚好是能记录的最大长度。

NULL标志位:很好理解标志该行数据中是否有空值

记录头信息 :如下图所示

行溢出 :

关于行溢出,即存储很长的字符串,在该字段会存储该字符串的前768个字节的前缀(字段超过768字节则为变长字段),并将整个字符串存储在uncompress blob页中。

行分布

前面说到过,页的物理地址是连续的,但是页内数据却是乱序的,理解起来可能有些抽象,下图将直观的展示出页内行记录的分布。

那我们在结合着上文说到的页和页之间构成双向链表的关系,下面给出了页结合行的结构图。

Page Directory

页目录,放了记录的相对位置,它是一个稀疏目录,一个目录指针(solts)包含多个记录,B+树索引本身并不能找到具体的一条记录,B+树索引能找到只是该记录所在的页。数据库把页载入内存,然后通过PageDirectory再进行二叉查找。只不过二叉查找的时间复杂度低,同时内存中的查找很快,因此通过忽略了这部分查找所用的时间。

Free Space

这一部分存储着释放的空间,这些空间构成了空闲空间链表。

BTree

根据上文描述的页结构最终可构建出innoDB的索引结构图,索引页为非叶节点 ,索引节点中存有对应数据页的指针, 数据页为叶子节点,所以我们通过索引查找记录,是先定位到页,再通过页内的稀疏索引查找对应记录。

 

END

后期会有专门讲解innoDB索引结构的分享哦!别忘了结合本文一起看奥!相信会有1+1>2的效果!

 

特别声明

本文部分插图来源于《mysql技术内幕-innoDB存储引擎第2版》和网络。

欢迎留言沟通!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值