浅析InnoDB Record Header及page overflow(1)

简介: 浅析InnoDB Record Header及page overflow

前言

土人有土办法,利用innodb_ruby观测验证innodb page header及overflow临界点。

这是一篇封存了两年的文章,最近拿出来重新整理发布。

1、背景信息

1.1 InnoDB Diagrams项目

首先看一下Jeremy Cole、Davi Arnaut两位大神联合维护的牛逼项目:InnoDB Diagrams

在这个项目中,详细介绍了InnoDB引擎数据结构、日志结构,以及InnoDB内部的运行机制。

为了配合这个项目,二位大神还开发了一个InnoDB数据文件解析工具 innodb_ruby

1.2 InnoDB Record Header

InnoDB Diagrams项目中有一张图介绍了InnoDB record header是如何构成的

image.png


关于这些头信息的解释可见文章 The physical structure of records in InnoDB,本文不赘述。

简言之,记住几条关键规则

  • 一条记录的record header,至少是5字节
  • 对record header影响最大的是变长列数量,及其是否允许为NULL的属性

关于变长列

  • 每个变长列,如果列长度 <128 字节,则需要额外1字节
  • 每个变长列,如果列长度 >=128 字节,则需要额外2字节
  • 如果没有任何变长列,则无需这额外的1-2字节
  • 变长类型为char/varchar/text/blob等

同学们可能会诧异,char为什么也当做变长类型了?这是因为,当字符集非latin1时,最大存储长度可能会超过255字节,例如 char(65) utf8mb4 最长就可以存储260字节,此时在record header中需要用2字节来表示其长度,因此也被当做变长类型了

关于列允许为NULL

  • 每个列如果允许为NULL,则增加 1bit,不足8bit也需要额外1字节
  • 例如只有2个列允许为NULL,只需要2bit来表示,但也需要占用1字节

P.S,在InnoDB的存储结构里,从tablespace到segment,再到extent、page,还是file层面,总有各种必要的header或trailer信息需要消耗额外的字节数,不像MyISAM那么简单。

1.3 innodb_ruby项目

上面提过,innodb_ruby工具可以帮助我们进一步理解InnoDB引擎数据结构、日志结构。

该项目用ruby语言开发(大神真是任性,选了这个比较冷门的开发语言)。

特别提醒,该项目已经多年未更新,有些数据类型发生了变化(例如最经典的5.6之后时间日期类型),它解析的可能就不准确了,在我下面的实测案例中也证实了这点。因此,我还用到另外一个辅助工具 innblock

1.4 innblock工具

由八怪开发,用于扫描和分析InnoDB page,详见 innblock | InnoDB page观察利器


2、定义不同数据类型时的record header消耗

根据上面的理论,我们接下来计算并验证当表里有各种不同的数据类型时,分别需要多少额外字节。

关于测试环境

  1. MySQL版本:Percona Server 5.7.22-22
  2. 测试配套工具:innodb_ruby & innblock

特别提醒,测试表的字符集为utf8mb4

经过计算和验证,最终可以得到以下几条结论:

  1. 每条记录的record header(下面简称RH)基础是5字节(简写成 RH=5)
  2. 每当表中多一个列允许为NULL,则额外增加1bit,且不足8bit时也需要消耗1字节(同理,不足16bit时需要消耗2字节)
  3. 每当表中多一个最大定义存储长度不超过255字节的变长列(char/varchar)时,额外增加1字节
  4. 每当表中多一个最大定义存储长度超过255字节的变长列(char/varchar/text/blob)时,额外增加2字节

由此我们可以推断出以下几种场景所需的record header大小横屏观看,下同)

场景 表定义 行长度
(字节)
record header
(字节)
备注说明
1 id int not null
提醒:无显式主键
28 5 5(RH)
+6(TRX_ID)
+7(ROLL_PTR)
+6(ROW_ID)
+4(INT) = 28
2 id int
提醒:无显式主键,且未指定not null
29 6 6(允许null) + 6 +7 +6
+4
= 28
3 id int not null
primary key(id)
提醒:id列是显式主键
22 5 5 + 6 + 7
+4
= 22
4 id int not null,
c1 char(10),
primary key(id)
c1列只存储一个字符'a'
34 7 7(char+null)+
6 + 7
+ 4 + 10(c1)
= 34
5 id int not null,
c1 varchar(10),
primary key(id)
c1列只存储一个字符'a'
25 7 7(varchar+null) +
6 + 7
+ 4 + 1(c1)
= 25

更多的场景,详见下面这个汇总表格

image.png




相关文章
|
存储 安全 关系型数据库
【InnoDB引擎如何管理Page页】
【InnoDB引擎如何管理Page页】
163 0
|
存储 关系型数据库 MySQL
浅析InnoDB Record Header及page overflow(1)
浅析InnoDB Record Header及page overflow
121 0
浅析InnoDB Record Header及page overflow(1)
|
存储 NoSQL 关系型数据库
浅析InnoDB Record Header及page overflow(2)
浅析InnoDB Record Header及page overflow
147 0
|
存储 NoSQL 关系型数据库
浅析InnoDB Record Header及page overflow(2)
浅析InnoDB Record Header及page overflow
|
26天前
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
1月前
|
存储 关系型数据库 MySQL
MySQL存储引擎详述:InnoDB为何胜出?
MySQL 是最流行的开源关系型数据库之一,其存储引擎设计是其高效灵活的关键。InnoDB 作为默认存储引擎,支持事务、行级锁和外键约束,适用于高并发读写和数据完整性要求高的场景;而 MyISAM 不支持事务,适合读密集且对事务要求不高的应用。根据不同需求选择合适的存储引擎至关重要,官方推荐大多数场景使用 InnoDB。
71 7
|
1月前
|
存储 关系型数据库 MySQL
Mysql索引:深入理解InnoDb聚集索引与MyisAm非聚集索引
通过本文的介绍,希望您能深入理解InnoDB聚集索引与MyISAM非聚集索引的概念、结构和应用场景,从而在实际工作中灵活运用这些知识,优化数据库性能。
144 7
|
2月前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
176 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
1月前
|
存储 关系型数据库 MySQL
MySQL引擎InnoDB和MyISAM的区别?
InnoDB是MySQL默认的事务型存储引擎,支持事务、行级锁、MVCC、在线热备份等特性,主索引为聚簇索引,适用于高并发、高可靠性的场景。MyISAM设计简单,支持压缩表、空间索引,但不支持事务和行级锁,适合读多写少、不要求事务的场景。
64 9