首先从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的语法分析器一样哈