写点什么

原来一条 select 语句在 MySQL 是这样执行的《死磕 MySQL 系列 一》

用户头像
咔咔
关注
发布于: 6 小时前
原来一条select语句在MySQL是这样执行的《死磕MySQL系列 一》

前言

看到蒋老师的第一篇文章后就收货颇丰,真是句句戳中痛点。


令我记忆最深的就是为什么知道了一个个技术点,却还是用不好 ?不管是蒋老师所说的 Redis 还是本系列要展开学习的 MySQL。


这是一个值得思考的问题,在大多数情况下,我们直接上百度搜索 MySQL 事务、MySQL 索引之类的词汇。


上述问题当然也是 MySQL 的几个核心问题之一,但如果我们都在不断地学习这些大的方面,我们怎么才能在学习某一个技能上有质的提升。


借用蒋老师的话术:“很多技术人都有一个误区,就是只注重零散的技术,没有建立一个完整的知识架构,缺乏系统观,然而,系统观却是至关重要的。在解决问题的时候,从某种意义上来说,拥有系统观,就意味着你有依据、有章法去定位并解决问题。”


假如你对这些话也深有体会,那就跟咔咔一起建立一套 MySQL 的知识框架,对于这种思想也是第一次实战,希望大家多多提意见。

一、从宏观的角度分析 MySQL

首先看一张经典图片



这幅图估计很多人都看到过,也是经典之作高性能 MySQL 里边的,如果有兴趣可以先看一下电子版的(如需要电子版可联系咔咔),感觉自己能看进去了,再去买书也来的急。


闲话少说,进入正题。


上图的客户端可以直接理解为 PHP、Java 等。接下来,你会看到连接、线程处理。这一部分并不是 MySQL 所特有的,而且大多数客户端、服务器都具有类似的结构。


因此,一般而言,MySQL 可以分为两层:Server 层和存储引擎层。


Server 层主要包括连接层、查询缓存、分析器、优化器、执行器等重要模块组成,这一层还包含了 MySQL 核心 Api 部分,比如常用的格式化时间、加密等。


存储引擎大家都很熟悉,因为在面试中不止一次的问过大家 Innodb、Myisam 存储引擎的不同。


所以想过没有,MySQL 为什么会有这么多的存储引擎呢?


一切技术起源于当下问题,同样在 MySQL 中也不例外。


MySQL 在存储引擎这一方面的架构是插件式的,即可以随意切换不固定,而且 MySQL5.5 版本存储引擎已经默认为 Innodb。

二、一条 SQL 执行要经过多少困难?

下图是咔咔之前培训时给发的资料



图中还有一个熟悉的陌生人查询缓存模块,该模块在 MySQL8.0 中已不存在。


关于该模块为何要被删除,后续的文章也将于大家交流。


首先,我们将大致了解当我们执行一条 SQL 语句时,如何在这个架构图中运行。

2-1 连接器

mysql -u root -p连接数据库命令,在执行之后,你将需要输入密码。当完成经典的 TCP 握手之后,连接器就开始发挥作用了。


如果码错误时,则返回Access denied for user ‘root‘@‘localhost‘ (using password: YES,错误编码 1045。


如果连接信息均正确,则此时将根据你输入的用户访问权限表来获取该用户的权限,此处必须清楚,当你登录成功后,即使其他人修改了你的权限,在这个连接未断开之前你的权限是不会发生改变的。


当你连接完成之后,如果你一直不做任何事情,执行 show processlist 将会看到一个 sleep,表示空连接。


那么你知道在 MySQL 中,如果连接成功后没有进行任何操作,多久会被自动中断?


可以执行show variables like 'wait_timeout';用于查看时间。



在 MySQL 中如果没有特别说明,那么所有的时间都是以秒为单位的,根据时间转换可以得知空连接持续 8 小时。

2-2 查询缓存

你需要注意的是,MySQL8.0 已经被取消了,这个问题不止说了一次了,特别是那些正在使用 MySQL8.0 以下版本的小伙伴要注意哈!当你切换到 8.0 时候,遇到这个问题不知道怎么解决。


MySQL8.0 为何取消查询缓存模块


这个模块的设计,把查询语句作为 key ,将结果作为 value 进行缓存,一旦这个表有更新,之前所有的缓存都会被清除掉。这就像你辛辛苦苦写的代码提交之后被别人覆盖一样难受。


MySQL8.0 以下的版本提供了一个参数 query_cache_type = enmand 来控制是否要使用查询缓存,在设置完成后,默认的 select 语句将不会被缓存。


如果确实可以使用部分场景,那么你可以将sql_cache添加到select关键字之后。


如果一条 select 语句之前被缓存过,那么结果集在这里就会直接返回,而没有缓存过的 select 语句就比较辛苦了,还要继续自己的漫漫长路。

2-3 分析器

MySQL8.0 之前,它会在进入分析器之前判断是否缓存,在 MySQL8.0 之后,连接器验证成功后就直接进入分析器。


分析器,根据字面意思来理解就是分析要执行的 SQL 语句是什么,要做什么。


比如执行select * from user where id = 1


MySQL 首先根据 select 判断这是一个查询语句,然后将 user 识别为表名,id 识别为字段名,这个过程被称为词法分析


下一步,需要知道该 SQL 的语法是否正确,进行语法分析,如果语法不对你就会看到You have an error in your SQL syntax错误。通常,将在 use near 中找到该错误。

2-4 优化器

到了这一步,MySQL 知道你要做什么,但是要选择最佳执行方案。


优化器都优化些什么?


举例来说:多个索引时选择那个索引、多表关联时连接顺序。


现在你是否想知道,优化器将优化多表关联的连接顺序,那在写 SQL 语句时是否就不必考虑连接顺序呢?


当然不是,能让 MySQL 少做事情就少做,还是一个准则用小表驱动大表。

2-5 执行器

通过要做什么、怎么做后这条 SQL 语句才会真正的被执行,先进行权限验证,若没有权限则直接返回权限错误,否则根据表定义的存储引擎,去使用对应引擎提供的接口。

三、总结


上图包含了正文的所有知识点,也是整个 MySQL 的大体执行流程图,后期文章都将围绕这几个要点展开。


坚持学习、坚持写作、坚持分享是咔咔从业以来所秉持的信念。但愿文章在偌大的互联网上能给你带来一点帮助,我是咔咔,下期见。

发布于: 6 小时前阅读数: 4
用户头像

咔咔

关注

还未添加个人签名 2021.04.08 加入

还未添加个人简介

评论

发布
暂无评论
原来一条select语句在MySQL是这样执行的《死磕MySQL系列 一》