1:执行一条 select 语句,期间发生了什么?
MySQL 的架构共分为两层:Server 层和存储引擎层,
Server层:负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现,主要包括连接器,查询缓存、解析器、预处理器、优化器、执行器等。另外,所有的内置函数(如日期、时间、数学和加密函数等)和所有跨存储引擎的功能(如存储过程、触发器、视图等。)都在 Server 层实现。
存储引擎层:负责数据的存储和提取。支持 InnoDB、MyISAM、Memory 等多个存储引擎,不同的存储引擎共用一个 Server 层。现在最常用的存储引擎是 InnoDB,从 MySQL 5.5 版本开始, InnoDB 成为了 MySQL 的默认存储引擎。我们常说的索引数据结构,就是由存储引擎层实现的,不同的存储引擎支持的索引类型也不相同,比如 InnoDB 支持索引类型是 B+树 ,且是默认使用,也就是说在数据表中创建的主键索引和二级索引默认使用的是 B+ 树索引。
执行流程、
连接器:建立连接,管理连接、校验用户身份;
查询缓存:查询语句如果命中查询缓存则直接返回,否则继续往下执行。MySQL 8.0 已删除该模块;
解析 SQL,通过解析器对 SQL 查询语句进行词法分析、语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;
执行 SQL:执行 SQL 共有三个阶段:
预处理阶段:检查表或字段是否存在;将 select * 中的 * 符号扩展为表上的所有列。
优化阶段:基于查询成本的考虑, 选择查询成本最小的执行计划;
执行阶段:根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端;
2:MySQL 一行记录是怎么存储的?
MySQL 的数据存放在哪个文件?SHOW VARIABLES LIKE 'datadir'; /var/lib/mysql/ 创建一个 database,会在该目录下创建一个以 database 为名的目录 包含三个文件
db.opt,用来存储当前数据库的默认字符集和字符校验规则 t_order.frm,t_order 的表结构会保存在这个文件 t_order.ibd,t_order 的表数据会保存在这个文件。表空间文件的结构是怎么样的?
表空间由段(segment)、区(extent)、页(page)、行(row)(重点)组成 InnoDB 提供了 4 种行格式,分别是 Redundant、Compact(重点)、Dynamic(5.7后默认)和 Compressed 行格式
COMPACT 行格式长什么样?
一条完整的记录分为「记录的额外信息」和「记录的真实数据」两个部分。
额外信息包括,变长字段长度列表(所占用的字节数 = 所有「变长字段长度」占用的字节数之和,单个变长字段最大字节数小于等于255字节用1字节表示,大于则用2字节)、
NULL 值列表(八个字段含以下占用1个字节、以上占用2个)、记录头信息(delete_mask、next_record、record_type)。
真实数据包括,row_id(没有主键或者唯一约束列时的隐藏主键ID 非必需)占用6个字节、trx_id(事务id 必需)占用7个字节、roll_pointer(上一个版本的指针 必需)占用7个字节行溢出后,MySQL 是怎么处理的?
发生行溢出,多的数据就会存到另外的「溢出页」中
MySQL 的 NULL 值是怎么存放的?
MySQL 的 Compact 行格式中会用「NULL值列表」来标记值为 NULL 的列,NULL 值并不会存储在行格式中的真实数据部分。
NULL值列表会占用 1 字节空间,当表中所有字段都定义成 NOT NULL,行格式中就不会有 NULL值列表,这样可节省 1 字节的空间。
MySQL 怎么知道 varchar(n) 实际占用数据的大小?
MySQL 的 Compact 行格式中会用「变长字段长度列表」存储变长字段实际占用的数据大小。
varchar(n) 中 n 最大取值为多少?
一行记录最大能存储 65535 字节的数据,但是这个是包含「变长字段字节数列表所占用的字节数」和「NULL值列表所占用的字节数」。所以, 我们在算 varchar(n) 中 n 最大值时,需要减去这两个列表所占用的字节数。