vlambda博客
学习文章列表

MYSQL入门到放弃(一)SQL的执行过程

首先说一说 MYSQL 的基础架构,假如你有一个很简单的表,如下列所示:

 

SELECT  *  FROM A WHERE ID = 1;

 

我们看到的只是执行输出了一个语句,得到了个结果,却很少在意这条语句的执行过程。


所以今天就想帮你把 MYSQL 拆解一下,借由拆解的机会,让你对 MYSQL 有一个更深入的了解。

 

下图是一个 MYSQL 的基础架构

 

 

 

可以大体看出,MYSQL 分为  server 层和存储引擎层。

 

server 层包括连接器,查询缓存,分析器,优化器,执行器等,涵盖了 MYSQL 大多数的核心功能,所有跨存储引擎的功能都在这一层实现,例如:存储过程,视图等。

 

存储引擎层负责数据的存储和提取,其架构模式是插件式的,支出 InnoDB,MYISAM,Memony 等多个存储引擎,目前,最常用的存储引擎是 InnoDB ,它从 MYSQL 5.5.5 版本之后就成为了默认的存储引擎。

 

也就是说,当你 create table 建表的时候,默认的就是 InnoDB 的存储引擎,当然,如果你想修改成其他的存储引擎,就在 create table 的建表语句后面加上 engine = memory,来指定想要使用内存引擎的表。

 

就根据一个 SQL 的执行过程,来看一看各个组件的具体功能。

 

连接器

 

连接到数据库,第一个接待你的就是连接器,主要负责与客户端建立连接,获取权限,维持与管理连接。即经过 TCP 握手之后,就要开始校验你的身份了。

 

当连接成功之后,管理员对此修改任何权限都不会起作用了,除非断开再次重新连接。

 

连接之后,如不做其他操作,连接进程会默认为 sleep 可通过 show processlist 进行查看,若长时间不进行操作,就会自动断开连接,可以通过设置 wait_timeout 的值来进行修改,默认值为 8。

 

这里我建议不要设置太长的时间,长连接时间过长,如果这时候有大量长连接,可能就会导致经常所说的 MYSQL 异常重启。

 

那么如何解决这个问题呢,这里有两种方案。

 

1.执行完一个相对于占内存比较多的 SQL,自动断开,再在使用时进行连接

 

2.或者通过初始化连接资源(mysql_set_connection)

 

查询缓存

 

执行完的 SQL 可能会通过 key - value 的形式存储到缓存当中,key 是 SQL 执行语句,value 是执行所得到的结果集,执行一个语句,通过连接器以后,会先到查询缓存去瞧一瞧,

有没有存储在里面啊,如果有,就直接返回结果集,没有,当然是继续走后面的执行流程。

 

虽然看上去,查询缓存,比较有利,但是并不是特别推荐使用的,因为查询缓存失效特别频繁,只要是对这张表的数据进行操作,缓存就会失效,但是呢,如果是你有一张静态表,比如说是系统的配置表,就很适合使用查询缓存。当然呢,是否使用查询缓存 可以把 query_cache_type 设置成 DEMAND,这样就不默认使用查询缓存啦。当然呢,MYSQL 8.0 之后的版本就取消掉了这个功能。

 

分析器

 

没有在查询缓存中获取到结果,就开始接下来的流程了,首先呢,得先让 MYSQL 知道你想要干什么,因此就会对你的 SQL 进行分析。分析有词法分析,语法分析。

     

词法分析,就是把 select、where 这种关键字分析出来,分析某个 词是字段啊,还是表啊。

     

在词法分析完成之后的结果,在进行语法分析,这时候分析,你的 SQL 是否符合 MYSQL 的语法,例如:select type from T wher id = 10 这个语句 where 少了一个 e 就会报错。

 

优化器

 

知道你想要做什么之后,就是该怎么做了,例如:SELECT * from A  join B where A.id = 1 and B.id = 20;

 

1.先去 A 表找符合 ID = 1 的,再去找 B 表 ID=20 的

 

2.先去 B 表找符合 ID = 20 的,再去找 A 表 ID=1 的

 

虽然得到的结果集是一致的,可选择的执行过程却不一样,这时候优化器就会帮你进行选择了,使用哪种方法,使不使用索引。

 

执行器

 

知道做什么该怎么做了,就开始正经的执行 SQL 语句了。

执行流程:

               1.通过 InnoDB 接口调取这个表,获取第一行的值,看看这个 ID 是否是 10,是,就放入结果集,不是就舍弃。


               2.再次通过接口取下一行,重复之前的逻辑。


               3.表扫描完毕,获取到所有满足条件的行组成结果集,将结果集返回给客户端。


随后你可以在数据库的慢查询日志中 字段 rows_examined 查询一共扫描了多少行。这个字段是累加的。