自存笔记,学习MySQL实战45讲


第一讲:一条SQL查询语句是如何执行的

MySQL架构理解

首先我们知道,MySQL是分为Server层和存储引擎层两部分的。

Server层里有连接器、查询缓存(MySQL8.0后被删除)、分析器、优化器、执行器等,负责构建MySQL的大部分功能;

存储引擎层采用插件式架构,可以支持不同的存储引擎,负责存储数据。通俗来讲,存储引擎层就像一个包裹,负责把存储引擎打包到一起,并向Server层提供读写接口

注意,不同的存储引擎共用一个Server层。也就是说,MySQL架构中,有一个Server层,一个存储引擎层,所有存储引擎公用一个Server层

执行过程

连接器

连接命令一般这么写:

1
mysql -h$ip -P$port -u$user -p

mysql是客户端工具,用来链接服务端。当完成TCP三次握手后,开始验证用户身份,用的是输入的用户名密码

  • 若用户名或者密码错误,则报错Access denied for user,然后结束
  • 若正确,则连接器会去权限表中查找用户拥有的权限。此后,这个链接中权限的判断逻辑,都依赖此时读到的权限

一个用户建立连接后,即时用管理员用户对这个用户权限做修改,也不会影响现存的链接,在建立新的链接才会使用新的权限设置

一个链接长时间不用会自动断开,需要重连才能执行请求。建议使用长连接,并定期断开再重连、执行 mysql_reset_connection 来重新初始化连接资源

查询缓存

连接建立之后,MySQL拿到查询请求,首先会去查询缓存看看,之前是否有执行过这条语句。之前执行过的语句+结果会以键值对形式存入内存。如果能命中key,则value会被直接返回

对更新压力大的数据库来说命中率极低,因为只要有对一个表的更新,这个表上所有的查询缓存都会被清空。

MySQL8.0版本开始直接删掉这块功能了

分析器

未命中或没用查询缓存,则分析器发力了

先做词法分析,根据输入的SQL语句,识别出里面字符串是什么。把输入的“select”识别出这是一个查询语句,把输入的“ID”识别成“列ID”

根据词法分析的结果和语法规则,进行语法分析,分析输入的语句是否合法

优化器

经过分析器,MySQL知道你要做什么。再用优化器选择方案—怎么做

优化器是决定再多个索引的时候使用哪个索引,在多表关联的时候决定各个表的关联顺序

1
select * from t1 join t2 using(ID)  where t1.c=10 and t2.d=20;
  • 既可以先从表 t1 里面取出 c=10 的记录的 ID 值,再根据 ID 值关联到表 t2,再判断 t2 里面 d 的值是否等于 20。

  • 也可以先从表 t2 里面取出 d=20 的记录的 ID 值,再根据 ID 值关联到 t1,再判断 t1 里面 c 的值是否等于 10。

这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。

执行器

MySQL通过分析器知道做什么,通过优化器知道怎么做,现在进入执行阶段

执行之前会先判断用户对这个表有没有执行权限

执行流程对比:

无索引情况,则全表扫描,具体流程如下:

  • 调用存储引擎接口获取表的第一行数据
  • 检查该行数据是否满足查询条件(例如 ID = 10),如果满足则将其加入结果集;若不满足则跳过该行
  • 继续调用存储引擎接口获取下一行数据,重复步骤 2,直到遍历完表中的所有行
  • 最后将满足条件的所有行组成结果集返回给客户端

有索引情况,利用索引来快速定位满足条件的数据,具体流程如下:

  • 通过索引结构快速定位到满足查询条件的第一行数据的位置
  • 调用存储引擎接口获取该行数据并加入结果集
  • 利用索引继续查找满足条件的下一行数据,重复步骤 2,直到没有满足条件的行
  • 将满足条件的所有行组成结果集返回给客户端

思考题

如果表 T 中没有字段 k,而你执行了这个语句 select * from T where k=1, 那肯定是会报“不存在这个列”的错误: “Unknown column ‘k’ in ‘where clause’”。你觉得这个错误是在我们上面提到的哪个阶段报出来的呢?

解析器阶段,解析词法的时候,没找到