MySQL执行流程是怎么样的?
MySQL的架构分为两层:Server层和存储引擎层。
- Server层负责与客户端建立连接、分析以及执行SQL。MySQL核心功能几乎都在Server层,它包含了连接器、查询缓存、解析器、预处理器、优化器、执行器等。
- 存储引擎层负责数据的存储和提取。存储引擎是插拔式的,支持InnoDB、MyISAM等存储引擎,不同的存储引擎共用同一个Server层。MySQL5.5以上版本默认的存储引擎是InnoDB。我们常说的索引数据结构,就是由存储引擎层实现的,不同的存储引擎支持的索引类型有差异。
接下来介绍一下一句SQL查询语句的执行流程。
第一步:连接器
连接器负责与客户端建立TCP连接、校验用户名和密码、管理连接、权限验证。
客户端首先向MySQL服务发起连接,MySQL是基于TCP协议进行传输的,所以经过TCP三次握手之后,就完成了TCP连接的建立。
建立连接之后,连接器就会开始验证客户端发送过来的用户名和密码是否正确,如果有误,就向客户端返回“Access denied for user”。
如果用户名密码都正确,连接器就会获取该用户的权限,然后保存起来,后续该用户在此连接的所有操作,都会基于此时(也就是校验用户身份成功之后)读到的权限进行权限判断。所以,如果一个用户已经建立了连接,即使管理员中途修改了该用户的权限,也不会影响该用户在此连接的操作。
第二步:查询缓存
连接器的工作完成之后,客户端就可以向MySQL服务发送SQL语句了,MySQL服务收到SQL语句之后,如果发现是SELECT语句,也就是查询语句,就会去查询缓存中查找缓存数据,这个查询缓存是以key-value形式存在于内存中的,key为SQL,value为SQL的查询结果。
查询缓存在MySQL8.0版本之后已经废弃,这里不多赘述。
第三步:解析器
解析器负责对SQL进行解析,首先判断SQL语法是否正确,如果不正确就会给客户端返回报错信息。如果正确,构建SQL语法树,给后面的模块去获取SQL类型、表名、字段名、查询条件等。但是解析器不会判断当前操作的表和字段是否存在。
第四步:预处理器
预处理器负责将SQL语句中的*符号转换为表上的所有字段(如有)。
并且会检查SQL语句中操作的表以及表的字段是否存在。
第五步:优化器
优化器负责确定SQL语句的执行计划。
第六步:执行器
执行器负责真正执行SQL,执行器会和存储引擎进行交互,交互是以记录(record,也就是我们理解的行)为单位的。
索引下推
索引下推(Index Condition Pushdown,简称ICP)实际上就是将上层(Server层)负责的部分事情,放到了下层(存储引擎层)处理。
举个例子,如果一张表里面有3个字段a、b、c,建立了联合索引(a,b,c),SQL语句中的筛选条件是: where a = xx and c = yy。
如果没有使用索引下推:
- 存储引擎层会到该索引中定位到所有a = xx的记录,然后对每一条记录执行回表,再将这些记录返回给Server层
- Server层在这些记录中筛选出c = yy的记录,并返回给客户端
如果使用了索引下推:
- 存储引擎层会到该索引中定位到所有a = xx的记录,因为该索引中包含了c字段,所以只有判断到c = yy的记录,才会回表查询并返回给Server层
- Server层将这些记录直接返回给客户端(注意,这里只是特殊情况,比如筛选条件还包含不在索引内的字段,d = zz之类的,Server层还需要使用这些条件进行进一步过滤)