二章_储存引擎

MySQL支持的存储引擎有好多种,它们的功能各有侧重,我们常用的就是ImoDB和MyISAM.其中InnoDB是服务器程序的默认存储引擎。

在Windows系统上启动服务器程序的方式有下面这些:

  • mysqld;
  • 将mysqld注册为Windows 服务。

启动客户端程序时常用的语法如下:
mysql -h主机名 -u用户名 -p密码

以查询请求为例,服务器程序在处理客户端发送过来的请求时,大致分为以下几个部分。

  • 连接管理:主要负责连接的建立与信息的认证。
  • 解析与优化:主要进行查询缓存、语法解析、查询优化。
  • 存储引擎:主要负责读取和写入底层表中的数据。

存储引擎的些常 用用法如 下所示:

  • 查看当前服务器程序支持的存储引擎:

SHOW ENGINES;

创建表时指定表的存储引擎:

  1. CREATE TABLE 表名(
  2. 建表语句;
  3. )ENGINE =存储引擎名称;

修改表的存储引擎:

ALTER TABLE 表名 ENGINE = 存储引擎名称;

三章_字符集和字符比较规则

  • 不同字符集储存相同的字符在内部储存的二进制位不同、字节数不同
  • 用不同的比较规则在字符比较时,返回结果也会不同

字符集的转化

字符集.png

字符集4个级别

  • 服务器级 ```sql —查看 SHOW VARIABLES LIKE ‘character_set_server’; #字符集 SHOW VARIABLES LIKE ‘collation_server’; #比较规则

—修改 character_set_server=gb2312 collation_server=gb2312_chianse_ci


- 数据库级
```sql
--查看
SHOW VARIABLES LIKE 'character_set_database'; #字符集
SHOW VARIABLES LIKE 'collation_database';  #比较规则

--创建
CREATE DATABASE [IF NOT EXISTS] 数据库名
[[DEFAULT] CHARACTER SET 字符集名] 
[[DEFAULT] COLLATE 比较规则名];

--修改
ALTER DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名] 
[[DEFAULT] COLLATE 比较规则名];

--删除
DROP DATABASE <数据库名>;
  • 表级 ```sql —查看 SHOW CREATE TABLE 表名;

—创建 CREATE TABLE [IF NOT EXISTS] 表名 (列信息) [[DEFAULT] ENGINE 储存引擎名称] [[DEFAULT] CHARACTER SET 字符集名] [[DEFAULT] COLLATE 比较规则名];

—修改 ALTER TABLE 表名 [[DEFAULT] CHARACTER SET 字符集名] [[DEFAULT] COLLATE 比较规则名];

—删除 DROP TABLE 表名;


- 列级
```sql
--查看
SHOW  FULL COLUMNS FROM 表名;

--创建
CREATE TABLE 表名(
  列名 字符串类型 [CHARACTER SET 字符集名] [COLLATE 比较规则名],
  其他列……
);

--修改
ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名] [COLLATE 比较规则名];

等级转换关系

5edc7342b4fc1d2ff3b14a1d9885d24.jpg

四章_InnoDB记录的储存结构

4.1 InnoDB页简介

InnoDB是一个将表中的数据存储到磁盘上的存储引擎,即使我们关闭并重启服务器,数据还是存在。而真正处理数据的过程发生在内存中,所以需要把磁盘中的数据加载到内存中。如果是处理写入或修改请求,还需要把内存中的内容刷新到磁盘上。而我们知道读写磁盘的速度非常慢,与读写内存差了几个数量级。当我们想从表中获取某些记录时,InnoDB 存储引擎需要一条一条地把记录从磁盘上读出来么?不,那样会慢死,InnoDB 采取的方式是,将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位。InnoDB 中页的大小一般为16KB。也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中。

系统变量innodb_page_size表明了InnoDB 存储引擎中的页大小,默认值为1684(单位是字节),也就是16KB.该变量只能在第一次初始化MySQL数据目录时指定,之后就再也不能更改了。在服务器运行过程中不可以更改页面大小。

4.2 InnoDB行格式

我们平时都是以记录为单位向表中插入数据的,这些记录在磁盘上的存放形式也被称为行格式或者记录格式。设计InnoDB存储引擎的大叔到现在为止设计了4种不同类型的行格式分别是COMPACT、REDUNDANT、DYNAMIC和COMPRESSED。随着时间的推移,他们可能会设计出更多的行格式,但是不管怎么变,这些行格式在原理上大体都是相同的。

4.2.1 指定行格式的语法

--创建或修改表的语句中指定记录所使用的行格式:
CREATE TABLE表名(列的信息) ROW_ FORMAT=行格式名称;

ALTER TABLE表名ROW FORMAT=行格式名称;

4.2.2 COMPACT行格式

com1行格式.png

(1)变长字段长度列表

变长字段是什么:
MySQL 支持一些变长的数据类型,比如VARCHAR(M)、VARBINARY(M)、各种TEXT类型、各种BLOB类型,变长字段中存储多少字节的数据是不固定的。我们也可以把拥有这些数据类型的列称为变长字段。也就是说这些变长字段占用的存储空间分为两部分:真正的数据内容、该数据占用的字节数。

储存哪些值:
变长字段长度列表只储存非NULL的变长字段的内容长度,如果某个记录为null,变长字段长度列表不进行存储

储存顺序:
在COMPACT行格式中,所有变长字段的真实数据占用的字节数都存放在记录的开头位置,从而形成一个变长字段长度列表,各变长字段的真实数据占用的字节数按照列的顺序逆序存放。

变长字段列表占用多少字节:
M:该字段最大储存字符数; W:该字段的字符集最多需要W个字节表示一个字符; L:实际储存的字符串占用的字节数。总结:如果该变长字段允许存储的最大字节数(M x W)超过255字节,并且真实数据占用的字节数(L)超过127字节,则使用2字节来表示真实数据占用的字节数,否则使用1字节。

(2)NULL值列表

储存哪些值:
主键列以及使用NOT NULL修饰的列都是不可以存储NULL值的,所以在统计的时候不会把这些列算在NULL值列表中。如果表中没有允许存储NULL的列,则NULL值列表也就不存在了

储存顺序和储存格式:
每个允许存储NULL的列对应一个二进制位,二进制位按照列的顺序逆序排列。

二进制位表示的意义如下: 二进制位的值为1时,代表该列的值为NULL; 二进制位的值为0时,代表该列的值不为为NULL;(MySQL规定Null值列表必须用整数个字节表示,如果不为整数个字节,则在字节的高位补0)

(3)记录头信息

比较重要,下个章节主要讲解;(https://www.yuque.com/u25074850/bb2gty/lwow6g#KQmoE
记录头信息固定由个字节组成,用于描述记录的一些属性。5字节也就是40个二进制位,不同的位代表不同的意思,前四位被称作info bit

(4)真实记录数据
MySQL为每个记录默认添加的列:

列名 是否必需 占用空间 描述
row _id 6字节 行ID,唯一标识一条记录
trx_id 6字节 事务ID
roll_pointer 7字节 回滚指针

4.2.3 REDUNDANT行格式

行格式2.png

4.2.4 DYNAMIC行格式和COMPRESSED行格式

这两种行格式类似于COMPACT行格式,只不过在处理溢出列数据时有点儿分歧:它们不会在记录的真实数据处存储列真实数据的前768字节,而是把所有的数据都存储到所谓的溢出页中,只在记录的真实数据处存储指向这些溢出页的地址。另外,COMPRESSED行格式会采用压缩算法对页面进行压缩。

五章 InnoDB数据页结构

数据页有很多分类

5.1 数据页结构快揽

InnoDB数据页结构示意图.png

7部分储存的内容
——————————————————————

5.2 记录页中的储存(Infimum+supremum 和 User Records)

在页的7个组成部分中,我们自己存储的记录会按照指定的行格式存储到User Records部分。但是在一开始生成页的时候,其实并没有User Records部分,每当插入一条记录时, 都会从FreeSpace部分(也就是尚未使用的存储空间)申请一个记录大小的空间,并将这个空间划分到UserRecords部分。当Free Space部分的空间全部被User Records部分替代掉之后,也就意味着这个页使用完了,此时如果还有新的记录插入,就需要去申请新的页了
过程图:
记录页储存过程 (1).png

5.21 详解记录头

记录头图解:
头信息.png

记录头信息的属性及描述:
——————————————————————————-

记录头信息相关描述:

  • deleted_flag:用来标记当前记录是否被删除,占用1比特。值为0表示没被删除,值为1表示被删除。(被删除记录还在磁盘中,因为真正移除它们,还需要在磁盘重新排列其他记录,会带来性能消耗。所有被删除的记录会形成一个垃圾列表,记录在这个链表的空间又叫做可重用空间。之后若有新的记录插入到表中,它们就可能覆盖掉被删除的这些记录占用的存储空间)
  • min_rec_flag:———————————————————————————-
  • n_owned:一个页面中的记录被分成若干个小组,每组最后一条记录的n_owned值表示组内记录数,组内其它n_owned值都为0

【什么是小组:https://www.yuque.com/u25074850/bb2gty/lwow6g#lMESD

  • heap_no:当前记录在堆的相对位置。(Infimum+supremum的heap_no值为0和supremum的heap_no值为1是固定的)

【什么是 Infimum+supremum:https://www.yuque.com/u25074850/bb2gty/lwow6g#PwFnB
IMG_20220615_234523_edit_743116713951710.jpg

  • record type:这个属性表示当前记录的类型。一共有4种类型的记录,其中0表示普通记录,1表示B+树非叶节点的目录项记录,2表示Infimum记录,3表示Supremum记录。
  • next_record:表示当前真实记录到下一条真实记录的距离,正值说明在下条记录在后面,负值在说明在下条记录在前面(下一条记录指的是按照主键从小到大顺序排列的下一条记录,数据结构为一个链表;supremum的nexe_record值为0)

IMG_20220615_233919_edit_742972902750691.jpg

5.22 Infimum+supremum虚拟记录

每个数据页自己生成,有5字节大小的记录头信息和8字节大小的一个固定单词组成;它们没有主键值,但规定Infimum记录表示在页里的记录中主键最小,supremum记录表示在页里的记录中主键最大(对于完整的记录来说,比较大小,就是比较记录主键的大小)
结构图:
IMG_20220615_230724_edit_742329938135164.jpg

5.3 Page Directory(页目录)

InnoDB的页目录制作过程如下所示:

  1. 将所有 正常的记录(包括Infimum和Supremum记录,但不包括已经移除到垃圾链表的记录)划分为几个组。
  2. 每个组的最后一条记录(也就是组内最大的那条记录)相当于“带头大哥”,组内其余的记录相当于“小弟”。“带头大哥”记录的头信息中的n_owned 属性表示该组内共有几条记录。
  3. 将每个组中最后一条记录在页面中的地址偏移量(就是该记录的真实数据与页面中第0个字节之间的距离)单独提取出来,按顺序存储到靠近页尾部的地方。这个地方就是Page Directory 。页目录中的这些地址偏移量称为槽(Slot),每个槽占用2字节。页目录就是由多个槽组成的。一个正常的页面也就是 16KB大小,即16384字节, 而2字节可以表示的地址偏移量范围是0~65535,所以用2字节表示一个槽足够了。

(图上:记录在存储设备中的排序;图下:按照记录主键从小到大的顺序组成一个单向链表的分组逻辑顺序
ee8c8d3953947a7c93463b7a00e1df8.jpg

5.31 分组:

  1. 分组规定:Infimum记录所在的组只能有一条数据,Supremum记录所在组拥有的记录在1~8条之间,剩下的分组记录条数在4~8之间。
  2. 当一个组插入8后,在插入一条记录,会将组拆分成两个组,其中一个组中4条记录,另一个5条记录。拆分过程中会新增一个槽,记录这个新增分组最大的那条记录的偏差量。

5.32 页目录如何查找数据

  1. 通过二分法确定该记录所在分组对应的槽,然后找到该槽所在分组中主键值最小的那条记录。
  2. 通过记录的next_record属性遍历该槽所在的组中的各个记录。

————————————————————————————————————-
25337309c9e44b5c414b680f2ff7e86.jpg

5.4 Page Header(页面头部)

为了存储数据页中记录的状态信息

5.5 File Header(文件头部)

表示页的通用信息,(校验和?双向链表)

5.6 File Trailer(文件尾部)

校验页的完整性,

六章 B+树索引