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 查询一共扫描了多少行。这个字段是累加的。