一、客户端与服务器连接的过程:
1、运行着的服务器程序和客户端程序 本质上都是计算机上的一个进程,所以客户端进程向服务器进程发送 请求并得到回复的过程本质上是一个进程间通信的过程
2、MySQL支持 下边三种客户端进程和服务器进程的通信方式:
(1)TCP/IP:
MySQL采用TCP作为服务器 和客户端之间的网络通信协议,MySQL服务 器会默认监听3306端口
(2)命名管道和共享内存:
Windows用户,那么客户端进程和服务器进程之间可 以考虑使用命名管道或共享内存进行通信
(3)Unix域套接字文件:
如果我们的服务器进程和客户端进程都运行在同一台操作系统为 类Unix的机器上的话,我们可以使用Unix域套接字文件来进行进程 间通信
3、服务器处理客户端请求
(1)本质:
客户端进程向服务器进程发送一段文本(MySQL语 句),服务器进程处理后再向客户端进程一段文本(处理结果)
(2)流程:
服务器程序处理来自客户端的查询请求大致需 要经过三个部分,分别是连接管理、解析与优化、存储引擎
(3)连接管理:
MySQL服务器会为每一个连接 进来的客户端分配一个线程,但是线程分配的太多了会严重影响系统 性能;
当连接建立后,与该客户端关联的服务器线程会一直等待客户端发送 过来的请求,MySQL服务器接收到的请求只是一个文本消息,该文本 消息还要经过各种处理
(4)解析与优化:
查询缓存、语法解析和查询优化;
I.查询缓存:
如果两个查询请求在任何字符上 的不同(例如:空格、注释、大小写),都会导致缓存不会命中。另 外,如果查询请求中包含某些系统函数、用户自定义变量和函数、一 些系统表,如 mysql 、information_schema、 performance_schema 数据库中的表,那这个请求就不会被缓存;
MySQL的缓存系统会 监测涉及到的每张表,只要该表的结构或者数据被修改,如对该表使 用了INSERT、 UPDATE、DELETE、TRUNCATE TABLE、ALTER TABLE、DROP TABLE或 DROP DATABASE语句,那使用该表的所 有高速缓存查询都将变为无效并从高速缓存中删除
II. 语法解析
客户端程序发送过来的请求只是一段文本而已,所以MySQL服务器程 序首先要对这段文本做分析,判断请求的语法是否正确,然后从文本 中将要查询的表、各种查询条件都提取出来放到MySQL服务器内部使 用的一些数据结构上来
III. 查询优化
MySQL的优化程 序会对我们的语句做一些优化,如外连接转换为内连接、表达式简 化、子查询转为连接等;
优化的结果就是生成一个 执行计划,这个执行计划表明了应该使用哪些索引进行查询,表之间 的连接顺序是啥样的,使用EXPLAIN语句来查看某个语句 的执行计划
(5)存储引擎
MySQL服务器把数据的存储和提取操作都封装到了一个叫存 储引擎的模块里;
连接管理、查询缓存、语法解析、查询优化这 些并不涉及真实数据存储的功能划分为MySQL server的功能,把 真实存取数据的功能划分为存储引擎的功能,各种不同的存储引擎向 上边的MySQL server层提供统一的调用接口(也就是存储引擎 API),包含了几十个底层函数,像"读取索引第一条内容"、“读取索 引下一条内容”、"插入记录"等等,MySQL server完成了查询优化后,只需按照生成的执行计 划调用底层存储引擎提供的API,获取到数据后返回给客户端就好 了
4、常用存储引擎:
二、字符:
1、请求从发送到结果返回过程中字符集的变化
2、字符集和比较规则:
(1)字符集:
请求从发送到结果返回过程中字符集的变化,主要有ASCII字符集、ASCII字符集、GB2312字符集、GBK字符集、utf8字符集
(2)比较规则:
比如utf8_general_ci,utf8表示对应字符集,general表示通用排序,ci表示不区分大小写;
比较规则是针对某个字符集中的字符比较大小的一种规则;
一个字符集可以有若干种比较规则,其中有一个 默认的比较规则,一个比较规则必须对应一个字符集;
比较规则的作用通常体现比较字符串大小的表达式以及对某个 字符串列进行排序中
三、InnoDB记录存储结构
1、InnoDB简介:
InnoDB是一个将表中的数据存储到磁盘上的存储引擎,将数据划分为若干个⻚,以⻚作为磁盘和内存之间交互的基本单位,InnoDB 中⻚的大小一般为 16 KB;
在一般情况下,一次最少从磁盘 中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到 磁盘中
2、InnoDB行格式:
(1)行格式或者记录格式:
我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的 存放方式也被称为行格式或者记录格式
(2)4种不同类型的行格式:
Compact、Redundant、Dynamic和Compressed行格式
3、Compact:
一条完整的记录其实可以被分为记录的额外信息和记录的真实数据两大部分:
(1)记录的额外信息:
服务器为了描述这条记录而不得不额外添加的一些信息,这些额外信息分为3类,分别是变⻓字段⻓度列表、NULL值列表和记录头信息;
I. 变长字段长度列表:
在Compact行格式中,把所有变⻓字段的真实数据占用的字节⻓度都存放在记录的开头部位,从而形成一个变⻓字段⻓度列表,各变⻓字段数据占用的字节数按照列的顺序逆序存放;
变⻓字段⻓度列表中只存储值为非NULL 的列内容占用的⻓度,值为 NULL 的列的⻓度是不储存的 ;
对于 CHAR(M) 类型的列来说,当列采用的是定⻓字符集时,该列占用的字节数不会被加到变⻓字段⻓度列表,而如果采 用变⻓字符集时,该列占用的字节数也会被加到变⻓字段⻓度列表
II. NULL值列表
Compact行格式把表中的某些列可能存储NULL值的列统一管理起来,存储到NULL值列表中;
如果表中没有允许存储 NULL 的列,则 NULL值列表 也不存在了;
每个允许存储NULL的列对应一个二进制位,二进制 位按照列的顺序逆序排列,二进制位的值为1时,代表该列的值为NULL。 二进制位的值为0时,代表该列的值不为NULL
III. 记录头信息
用于描述记录的记录头信息,它是由固定的5个字节组成,5个字节也就是40个二进制位,不同的位代表不同的意思
(2)记录的真实数据:
记录的真实数据除了几个我们自己定义的列的数据以外,MySQL会为 每个记录默认的添加一些列(也称为隐藏列),包括:
InnoDB存储引擎会为每条记录都添加 transaction_id 和 roll_pointer 这两个列,但是 row_id 是可选的(在没有自定义主 键以及Unique键的情况下才会添加该列)
示例:
4、Redundant行格式
字段⻓度偏移列表:没有了变⻓两个字,意味着Redundant行格式会把该条 记录中所有列(包括隐藏列)的⻓度信息都按照逆序存储 到字段⻓度偏移列表;
多了个偏移两个字,这意味着计算列值⻓度的方式不像 Compact行格式那么直观,它是采用两个相邻数值的差 值来计算各个列值的⻓度;
使 用Redundant行格式的CHAR(M)类型的列是不会产生碎片的。
一个行中的所有列(不 包括隐藏列和记录头信息)占用的字节⻓度加起来不能超过65535 个字节!
5、Dynamic和Compressed行格式
四、InnoD 数据⻚结构
1、数据⻚(索引(INDEX)⻚):
存放我们表中记录的那种类型的⻚
2、数据页结构示意图:
File Header:文件头部,⻚的一些通用信息;
Page Header:⻚面头部,数据⻚专有的一些信息;
Infimum + Supremum:最小记录和最大记录,两个虚拟的行记录;
User Records:用户记录,实际存储的行记录内容;
Free Space:空闲空间,⻚中尚未使用的空间;
Page Directory:⻚面目录,⻚中的某些记录的相对位置,也就是各个槽在⻚面中的地址偏移量,大小不固定,插入的记录越多,这个部分占用的空间越多;
File Trailer:文件尾部,校验⻚是否完整
3、记录在⻚中的存储:
在一开始生成⻚的时候,其实并没有User Records这个部分,每当我们插入一条记录,都会从 Free Space部分,也就是尚未使用的存储空间中申请一个记录大小的空间划分到User Records部分,当Free Space部分的空间全部被User Records部分替代掉之后,也就意味着这个⻚使用完了,如果还有新的记录插入的话,就需要去申请新的⻚了
4、记录头信息:
delete_mask:标记该记录是否被删除;
min_rec_mask:B+树的每层非叶子节点中的最小记录都会添加该标记;
n_owned:表示当前记录拥有的记录数,也就是该组 内共有几条记录;
heap_no:表示当前记录在记录堆的位置信息;
record_type:表示当前记录的类型,0表示普通记录,1表示B+树非叶节点记录,2表示最小记 录,3表示最大记录;
next_record:表示下一条记录的相对位置
记录按照主键从小到大的顺序形成 了一个单链表
5、页目录:
在一个数据⻚中查找指定主键值的记录的过程分为两步:
通过二分法确定该记录所在的槽;
通过记录的next_record属性遍历该槽所在的组中的各个记录
五、B+树索引
1、