深入学习MySQL,从概览MySQL逻辑架构开始。
首先来看一下MySQL的逻辑架构图:
MySQL逻辑架构大概可以分为三层:
值得一提的是在MySQL8.0中取消了查询缓存,大概的理由是查询缓存存在严重的可伸缩性问题,并且很容易成为严重的瓶颈缓存,将缓存移动到客户端能收获更好的性能。
通过一条查询语句的执行过程,来了解一些关键的部件:
mysql> select * from T where ID=10;
首先,需要连接数据库。
当客户端(应用)连接到MySQL服务器时,服务器需要对其进行认证。认证基于用户名、原始主机信息和密码。
连接命令:
mysql -h$ip -P$port -u$user -p
除了基本认证之外,连接器还会进行一些线程的处理。
每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中执行,该线程只能轮流在某个CPU核心或者CPU中运行。服务器会负责缓存线程,因此不需要为每一个新建的连接创建或者销毁线程。
对于SELECT语句,在解析查询之前,服务器会先检查查询缓存(Query Cache),如果能够在其中找到对应的查询,服务器就不必再执行查询解析、优化和执行的整个过程,而是直接返回查询缓存中的结果集。
但不推荐使用查询缓存,为什么呢?因为查询缓存往往弊大于利。
查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。对于更新压力大的数据库来说,查询缓存的命中率会非常低。除非你的业务就是有一张静态表,很长时间才会更新一次。比如,一个系统配置表,那这张表上的查询才适合使用查询缓存。
好在MySQL也提供了这种“按需使用”的方式。可以将参数query_cache_type设置成DEMAND,这样对于默认的SQL语句都不使用查询缓存。而对于确定要使用查询缓存的语句,可以用SQL_CACHE显式指定,如下:
mysql> select SQL_CACHE * from T where ID=10;
上面也提到了MySQL8.0彻底废弃了查询缓存的功能。
如果缓存没有命中的话,MySQL会对查询语句进行解析。简单说解析的作用将我们人能看懂的SQL解析成MySQ能识别的语言。
解析器先会做“词法解析”。输入的是由多个字符串和空格组成的一条SQL语句,MySQL需要识别出里面的字符串分别是什么,代表什么。
MySQL从输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名T”,把字符串“ID”识别成“列ID”。
做完了这些识别以后,就要做“语法解析”。根据词法解析的结果,语法解析器会根据语法规则,判断输入的这个SQL语句是否满足MySQL语法。
经过了解析器器,MySQL知道我们要干什么。
接下来并不是直接执行,而是会在优化器这一层进行优化,优化器是个非常复杂的部件,它会帮我去使用他自己认为的最好的方式去优化这条 SQL 语句,并生成一条条的执行计划。
例如在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。比如你执行下面这样的语句,这个语句是执行两个表的join:
mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。
优化器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。如果你还有一些疑问,比如优化器是怎么选择索引的,有没有可能选择错等等,没关系,我会在后面的文章中单独展开说明优化器的内容。
MySQL通过解析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,执行器会根据一系列的执行计划去调用存储引擎的接口去完成SQL的执行。
开始执行的时候,要先判断一下你对这个表T有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下所示(在工程实现上,如果命中查询缓存,会在查询缓存放回结果的时候,做权限验证。查询也会在优化器之前调用precheck验证权限)。
mysql> select * from T where ID=10; ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'
如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
比如我们这个例子中的表T中,ID字段没有索引,那么执行器的执行流程是这样的:
至此,这个语句就执行完成了。
对于有索引的表,执行的逻辑也差不多。第一次调用的是“取满足条件的第一行”这个接口,之后循环取“满足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。
参考:
【1】:《高性能MySQL》
【2】:极客时间 《MySQL实战45讲》
【3】:《MySQL技术内幕 InnoDB存储引擎》
【4】:MySQL 8.0: Retiring Support for the Query Cache
【5】:头条二面: 详解一条 SQL 的执行过程