Mysql—Innodb引擎 逻辑结构

一、Innodb引擎简介

Innodb引擎是事务安全的Mysql存储引擎,其设计上采用了类似于oracle的设计架构,该引擎存在于mysql发布的任何的二进制版本之中,正是由于Innodb引擎的存在,使得Mysql更具有魅力。

从Mysql的5.1版本开始,可以动态的加载引擎,出现所谓的Innodb plugin,在Mysql5.5版本将Innodb升级到1.1.x版本,5.6则将Innodb引擎升级至1.2.x版本,各个版本的功能简介如下图所示:

 如今Mysql已经更新到8.x.x的版本,用的较多的版本普遍为5.6及以上,但不乏还有在用老版本的用户,因为Innodb1.0.x不支持多回滚段,因此并发事务数量是有限制的(1023),因而建议使用Mysql5.6及其以上版本,无论是在速度上还是在功能上都有很大的提升。

二、Innodb引擎文件组织结构

1.物理文件的组织

Mysql使用插件式存储引擎的体系结构方式,我们都知道Mysql数据的存储是以表的形式组织的,因此不管使用何种引擎,都需要文件来存储表结构的定义,这个文件就是frm文件,所有的 MySQL 表都会在硬盘上创建一个frm文件用来描述表的格式或者说定义。

除了表结构定义frm文件以外,还有包括各种日志文件,Mysql常见的日志分为:错误日志(error log)、二进制日志(binlog)、慢查询日志(slow query log)、查询日志(log),这些日志可以帮助Mysql对系统运行状态做全面的诊断,以此来保证在Mysql数据库层面平稳的运行。(日志在后边文章详细介绍)

以上是Mysql数据库本身的数据文件,和存储引擎无关。除了Mysql本身的数据之外,每种存储引擎还会有属于自己的一些文件,例如与Innodb存储引擎相关的重做日志文件(redo log)、回退日志文件(undo log)、表空间文件(ibd)等。

1.1 表空间文件

InnoDB采用按照表空间(tablespace)存放数据的方式,默认会创建10M大小的名为ibdata1的文件,可以通过参数innodb_data_file_path调整文件的位置,并且支持配置多个文件,可以自动扩展大小,设置完ibdata文件之后,所有的Innodb创建的表的数据都会存储在该共享表空间之内。除此之外,也可以通过innodb_file_per_table参数配置来调整数据共享文件方式,当配置了该参数之后,每一个表都会有独立的表空间文件,命名格式为tableName.ibd。这些单独的表空间会存储数据、索引以及插入缓冲等信息,其他信息例如事务、回滚段等信息还是放在默认的默认的表空间中,下图为关于表空间文件的设置参数:

 关于Innodb表空间的描述如上,Innodb表空间文件存储结构大致如下图:

1.2 重做日志文件

重做日志文件即redo log file,官方称之为Innodb引擎的日志文件,引擎至少包含一个文件组(group),且每组至少会有两个文件ib_logfile0和ib_logfile1,并且提供组的镜像功能,可以将组的复制文件置于不同磁盘,保证文件高可用。当实例出现失败后,例如因为断电导致Mysql异常终止服务,此时redo log就会发挥其作用了,实例重启后会根据该日志将数据恢复至断电前的时刻,保证数据的一致性。日志文件每个大小相同,以循环的方式写入,即先写入1文件,满了之后在写2,满了之后再回去覆盖1继续写,如此循环,如下图:

关于重做日志i文件有几个配置参数:

nameeffectremark
innodb_log_file_sizeredo log file的大小每个文件大小相同,默认innodb 1.2.x之前最大4M,1.2.x最大512G
innodb_log_files_in_group日志文件组的日志文件数量默认是2
innodb_mirroried_log_groups日志镜像文件组的数量默认是1,即没有镜像
innodb_log_group_home_dir日志文件组的位置 
innodb_flush_log_at_trx_commit重做日志事务提交刷盘方式值分为 0 1 2,含义见其它讲解

此处关于redo log file大小的设置有些讲究,文件太大可能会使得恢复时间变长,太小则可能会使一个事务在日志文件频繁切换,影响性能,并且会导致频繁的check point,导致性能抖动。重做日志的写入方式以缓存--磁盘的方式进行,先写入redo log buffer,在以一定的条件写入磁盘,减少sync的操作,提升性能。

2.底层逻辑结构概述

Mysql Innodb存储引擎(5.6V)的官方基本结构如下图所示,

Innodb底层数据结构逻辑上分为TableSpace(表空间)、Segment(段)、Extend(区)、Page(页),因此对于Innodb引擎来说最小的操作单位是页,默认大小为16k(支持参数配置修改),文件系统的操作最小为4k,磁盘的最小操作单位为扇区,大小为512b,下图为mysql逻辑底层数据结构:

2.1 TableSpace(表空间)

上边已经提到过表空间一次,表空间是逻辑存储的最高层,所有的数据存储在表空间中,上文提到了innodb_file_per_table参数控制,配置之后每一张表都会生成自己的ibd表空间文件,但是该文件只存储数据、索引、插入缓冲等,其他的信息例如插入缓冲索引、回滚信息还是会放在默认的全局ibdata1空间文件中,也就是说当创建一张表,一方面会生成ibd文件,另一方面会在ibdata1文件存储表的结构等信息。

2.2 Segment(段)

表空间是由段来组成,它是一个逻辑概念,用来管理物理文件,是构成索引、表、回滚段的基本元素。表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。InnoDB存储引擎表是索引组织的(index organized),因此数据即索引,索引即数据。那么数据段即为B+树的页节点,索引段即为B+树的非索引节点。段的管理基本基于mysql引擎自己的管理,如何特殊情况,无需DBA进行额外的管理。

创建一个索引(B+树)时会同时创建两个段,分别是内节点段和叶子段,内节点段用来管理(存储)B+树非叶子(页面)的数据,叶子段用来管理(存储)B+树叶子节点的数据;也就是说,在索引数据量一直增长的过程中,所有新的存储空间的申请,都是从“段”这个概念中申请的。

2.3.Extend(区)

段是个逻辑概念,Innodb引入了区的概念,在代码中被称为extent;区是由64个连续的页组成的,每个页大小为16KB,即每个区的大小为1MB(不可更改)。区是构成段的基本元素,一个段由若干个区构成,一个区是物理上连续分配的一段空间,每一个段至少会有一个区,在创建一个段时会创建一个默认的区。如果存储数据时,一个区已经不足以放下更多的数据,此时需要从这个段中分配一个新的区来存放新的数据。一个段所管理的空间大小是无限的,可以一直扩展下去,但是扩展的最小单位就是区。

2.4. Page(页)

页是构成区的基本单位,是InnoDB磁盘管理的最小单位。,页的大概分类如下:

  • 数据页(B-tree Node)
  • Undo页(Undo Log Page)
  • 系统页(System Page)
  • 事务数据页(Transaction system Page)
  • 插入缓冲位图页(Insert Buffer Bitmap)
  • 插入缓冲空闲列表页(Insert Buffer Free List)
  • 未压缩的二进制大对象页(Uncompressed BLOB Page)
  • 压缩的二进制大对象页(Compressed BLOB Page)

在逻辑上(页面号都是从小到大连续的)及物理上都是连续的。在向表中插入数据时,如果一个页面已经被写完,系统会从当前区中分配一个新的空闲页面处理使用,如果当前区中的64个页面都被分配完,系统会从当前页面所在段中分配一个新的区,然后再从这个区中分配一个新的页面来使用;从innodb1.2.x版本开始,支持参数调整叶的大小,innodb_page_size为4k、8k,一个区中的叶的总数就会变256、128,因为区的大小是不会变的(1M)。

页是有多种类型的,本次详细介绍一下数据页的基础结构,B-tree node也就是所谓的数据页,是真是数据存储的地方,其结构大致如下:

  • File Header
  • Page Header
  • Infimum and Supremum Records
  • User Records
  • Free Space
  • Page Directional
  • File Trailer

其中File Header、Page Header以及File Trailer是固定大小的,依次为38、56和8字节大小,其他的User Recods、Free Space以及Page Directional是实际数据存储的位置,因此会根据实际的数据动态变化。

2.4.1 File Header

File Header描述了该数据页的一些基本头信息,占用38字节大小,包括页的类型、LSN以及上下页的指针等信息,结构如下图:

Innodb存储引擎页的类型(FILE_PAGE_TYPE)主要包括数据页、索引页以及Undo Log页等,具体分类如下:

2.4.2 Page Header

Page Header记录了页的一些状态信息,占用56字节,例如:该页中的记录数、最大事务ID以及索引ID等,具体信息如下:

2.4.3 InFimum and SupreMum Records

在Innodb的数据页中,会存在两条虚拟的记录,标识开始以及结束的位置,分别为Infimum和SupreMum Records,用来限定记录的边界,前者代表最开始的记录,比该页任何主键值都小,后者代表末尾结束的记录,是比任何主键都大的记录,这两个值在页创建的时候就有了,并且不可删除,在页中的结构如下图所示:

 2.4.4 User Record and Free Space

User Record就是下文即将介绍的行记录信息,即真实的数据信息;Free Space就是没有使用的空间,当数据记录删除时,该空间将会加入到空闲链表中,以供后续使用。

2.4.5 Page Directional

Page directional(页目录)存放了记录的相对位置,是相对于页的相对位置,有时候把这些目录指针称为槽(slots)或者目录槽(directionl slots)。在Innodb引擎中,并不是每一个记录都有一个槽一直对应,实际上这个目录是一个稀疏目录,即一个槽中可能包含多个目录。伪记录Infimum的n_owned值为总为1,Supremum的n_owned值为[1,8],其他用户记录取值范围是[4,8],当记录插入或删除时,需要对目录进行分裂或平衡的维护操作。在slots中的记录按照索引键的顺序排序,这样可以通过二叉查找快速找到记录的指针。

例如,现在有数据(i,a,b,d,c,e,g,h,i,j,k),如果每个槽放4个指针,那么slots中记录可能是(a,e,i)。因为在Innodb中索引是到叶子结点的,因此通过二叉查找并不能确定到记录,只能找到对应的叶子结点,在节点内部通过Page direcional(稀疏目录)找到大概的位置,再通过每个记录里的next record指针进行寻找匹配,从而找到服务要求的记录返回。

2.4.6 File Trailer

为了检测页是否完成的刷到磁盘(如可能发生在写入的过程中发生磁盘损坏或者关机等),Innodb设置了File Tralier部分。File Tralier中只含有一个部分FIL_PAGE_END_LSN,占用8个字节,前四个字节是Checksum,后四个字节和File Header的FIL_PAGE_LSN相同,将这两个值和File Header中的FIL_SPACE_OR_CHECKSUM和FIL_PAGE_LSN进行比较,以保证数据的完整性。

2.5 行(row)

Mysql存储引擎是面向列进行存储的,因为在数据页中,数据是按照行记录一条一条存储的,并且每个页最多存储16K/2-200(7992)条记录,记录在页中存储的格式分为Compact和Redundant两种方式,其中Redundant是为了兼容老版本而存在的,在Mysql5.1版本默认的行模式是Compact模式,下图两种模式下得record存储结构:

 

  • 变长字段列表
    描述了变长非null字段的所占的长度列表,是按照字段顺序逆序排列的,长度不超过255字节的,用1字节表示,长度超过255字节的,用2字节表示,变长字段的描述长度不可超过2字节,因此变长字段最大占用2^16(65535)字节。
  • null标志位
    该字段记录了,字段中值为NULL的列的情况,1为null,0为非null,长度为1字节大小,例如:06,转为二进制00000110,
    当null列值超出8个后,会自动扩展NULL标志位的长度。
  • 记录头信息
    记录头信息长度为5字节,记录了该记录的一些状态信息,包括记录的类型、下一条的记录指针以及删除的标识等,具体字段如下图所示:

  • 列信息
    列信息就是具体的记录的字段内容了,其中null值的字段除了占用null标志位以外,不占用任何空间。其中除了用户自定义的表的列的字段以外,还会增加事务ID和回滚指针列,分别为6字节和7字节的大小。如果还使用了rowId的话,还会存储rowid数值。

    另外一种方式Redundant行模式在上面图中展示出来,首先是字段长度偏移列表,长度规则与Compact相同。后面记录头信息占用6字节长度(Compact占用5字节),所存储的信息也在上图展示出,其中n_field字段记录了共有多少列,占用10位,这个限制使得引擎最多只能建立1023个字段;lbate_offs_flag记录了偏移列表的长度;最后就是实际存储的每个列的具体值了。
     

三 资源地址

官网:https://www.mysql.com

文档:《Mysql技术内幕-innodb存储引擎》《高性能Mysql》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值