本篇围绕MySQL数据库的底层存储模型、列类型来聊聊数据库表设计及建模中要注意的事项,剖析最根源的底层物理存储文件,用最真实的数据剖析来证明和解答开发过程中的疑惑。

在一些技术谈资、面试沟通过程中,MySQL特别是我们常用的Innodb存储引擎,是非常高频的话题点,而现实中不难发现,很多朋友都浅尝辄止,只能“照本宣科”被动背诵一些概念,遗憾的是这并不足以让我们“精通”。究其主要原因还是因为物理存储文件的结构过于复杂,它的“可观测性”并不友好,并且,对于一般的软件开发者而言,与数据库的交互窗口更多聚焦在数据库工具界面,鲜有机会接触到物理存储内部,浮于概念化。

本篇的目的就是解开MySQLInnodb的神秘面纱直击第一现场来感受真实的数据存储,分析建模设计过程中列类型的影响,帮助更好地做好“精挑细选”。

探查真实的物理存储

关于Innodb部分的学习推荐如下资料入手和探究:

MySQL官方文档

MySQL技术内幕-Innodb存储引擎

Innodb Ruby(Innodb存储文件解析工具)

innodb文件分析工具innodb_ruby使用操作

Innodb物理存储层层剥开

数据库文件存储位置

MySQL把我们的数据存储在哪里了?可以在命令行或数据库交互界面输入show variables like 'datadir'得到答案,即数据库文件存储位置。


sql复制代码
-- 如:show variables like 'datadir'
variable_name value
datadir /usr/local/mysql/data/

我们再来创建一个数据库,取名为test,如下:


sql复制代码
create database test;

创建库后,我们在/usr/local/mysql/data/路径下得到一个名为test的文件夹,即新数据库空间存储路径,会用来存储该数据库的所有信息。

我们再来创建一张测试表,也取名为test,如下:


sql复制代码
CREATE TABLE `test` (
  `col_1` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`col_1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

创建表后,我们在/usr/local/mysql/data/test路径下得到 test.frmtest.ibd两个文件,frm格式文件是MySQL架构层对于表结构定义的文件,与具体的存储引擎无关,而ibd文件则是Innodb存储引擎独有的,表结构选择该引擎后会以该格式文件进行物理存储,下面我们针对ibd文件进行深入分析。

ibd文件层层分解

对于一个ibd文件而言,也是有层次、有组织结构的。整体上它是一个独立的表空间,只为一张表而服务(一般会这样配置)。

从整体到具体、从大到小层层分解的话,可以描述为表空间(tablespace)段(segment)区(extent)页(page),会从抽象到具体,从逻辑到现实,接近我们事实数据的部分。

💁 通俗解释:

一般而言,表空间(tablespace)段(segment)区(extent)是层次结构中组织数据的抽象概念,是为层级服务的,像是学校年级班级的概念。

页(page)才是真实存储和控制业务数据的原子结构,像是老师学生的个体,每一个个体的信息都存储为行数据(Row)