首先从Mysql的整体去了解Mysql的全貌,来直接看一下一个简单的Mysql的执行流程

比如说:

select * from user where id = 1;

其内部的执行流程可以简单可以概括为

图片

从宏观角度来看,整个Mysql在接受到客户端的链接后,分为了两个层面去解决这个问题

Server层和存储引擎层

Server层包含了连接器,缓存 分析 优化器 执行器

并且包含Mysql日常涉及到的内置函数

存储引擎层则负责了数据的存储和提取,整体上来看是插件式的,支持InnoDB,MyISAM 等

在5.5之后,默认的引擎从MyISAM转为了InnoDB,当然这个支持手动的指定

比如通过在建表的时候create table后面加入engine=memory来指定内存引擎来创建表

接下来分开的看这两个部分,首先是Server中的连接器

客户端作为一个客户来访,必然有一个接待客服的部件,就是连接器,负责和客户端建立连接,获取客户的权限,维持和管理连接

一般不建议在连接命令中直接输入密码,可能导致密码泄露,在连接完成后,也就TCP的三次握手完成后,连接器会开始认证你的身份,如果认证通过了,会通过用户表查询出拥有的权限,并且判断权限,后续的所有操作都是基于现在读取到的权限

(也就是说,一个用户成功连接后,哪怕权限被修改了,也不会影响已经连接的权限)

连接完成后,这个连接处于空闲状态,可以在show processlist命令看到,其中Command列显示为Sleep的一列

如果建立起连接太长时间都没有反应,就会自动断开,默认8小时,参数是由wait_timeout控制的

连接断开之后,客户端再次有请求的时候,就会出现错误提醒

数据库中,建议使用长连接,但是长连接会导致使用内存特别快,因为Mysql在执行过程中占用的内存是在连接中的,太长的话会到导致长时间积累,最后OOM

为了避免出现OOM的事情,可以考虑定期的断开长连接

或者考虑在执行一个大操作之后使用 mysql_reset_connection 重新初始化连接

然后连接之后进行执行语句,但是会在进入执行器之前先查询缓存

mysql会以key-value的形式存储,key是查询的语句,value是查询的结果,如果能查询出这个key,那么会直接返回value

但是并不建议使用缓存,因为缓存并不耗时

因为缓存的实效很频繁,只要有一个表的更新,这个表上所有查询都会被清空,所以除非是一个静态表,不然不建议使用缓存

现在Mysql提供了按需进行缓存的方式,可以先将query_cache_type设置为DEMAND,让需要缓存的语句,加上SQL_CACHE指定

select SQL_CHACHE * from T where ID =10;

在Mysql 8.0之后已经没有查询缓存功能了

分析器:

也和Java的编译器一样,将语句转换成语法树,首先是Select 或者 update进行相关确定

如果在语法分析之后发现了错误,会爆出 You have an error in your SQL syntax

而且会提供会在哪里出现错误了

优化器,

就是选择是否使用索引,或者使用哪个索引,以及在多表联查的时候,选择表的查询顺序

执行器

首先会判断用户是否有执行这个语句的权限,如果有才会进行执行,

然后执行流程如下:

调用InnoDB引擎去取表的第一行,判断是否符合逻辑,如果符合则会将其放在结果集,不是则跳过,

依次重复直到表的最后一行,或者在有序的情况下不满足情况

然后返回结果集

如果开启了慢查询日志,能看到一个 rows_examined的资源,也就是扫描了多少行,但是这个值并不一定准确

最后说一句,如果执行了select语句,但是查询的字段不存在,那么会在分析器阶段报错,如同Java的语法分析器一样哈

发表评论

邮箱地址不会被公开。 必填项已用*标注