先上图,再解释
client:当我们发起一个查询请求的时候,首先会到MySQL的客户端,这里会按照通信协议连接服务端,也会进行相关的权限校验。
查询缓存:这里的查询缓存和mybatis的查询缓存基本相同,必须要求SQL语句和参数都相同才能命中,所以概率极低,没有使用价值,默认这个缓存是不开启的,如果开启且命中了缓存则直接返回数据。
解析器:词法解析和语法解析,词法解析将完整的SQL解析为一个个单独的部分,比如select、from、where等,得到的结果是一颗解析树,语法解析主要是对SQL语句进行语法检查,所以如果是缺少括号或者是多了个逗号之类的错误会在这一步被检查出来。
预处理器:主要是进行语义解析,在拿到解析器返回的正确解析树之后,预处理器会进一步对语义进行校验,比如字段不存在、表不存在类型的错误就是在这一阶段被检查出来的。
-
查询优化器:这时候已经获得了棵比较规范的树,接下来查询优化器会将其转化为执行计划,MySQL采用的是CBO-基于成本的查询优化器,它会根据SQL语句所涉及的表、索引、行数等信息计算出执行SQL所需的成本值,并选择一个最优方案作为执行计划,当然,由于MySQL理解不了业务,我们也可以通过 /+ .../*的语法控制优化器的行为,作出最符合当前情况的选择。示例:
SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33; SELECT /*+ BKA(t1) NO_BKA(t2) */ * FROM t1 INNER JOIN t2 WHERE ...; SELECT /*+ NO_ICP(t1, t2) */ * FROM t1 INNER JOIN t2 WHERE ...; SELECT /*+ SEMIJOIN(FIRSTMATCH, LOOSESCAN) */ * FROM t1 ...; EXPLAIN SELECT /*+ NO_ICP(t1) */ * FROM t1 WHERE ...; SELECT /*+ MERGE(dt) */ * FROM (SELECT * FROM t1) AS dt; INSERT /*+ SET_VAR(foreign_key_checks=OFF) */ INTO t2 VALUES(2);
执行器:调用存储引擎的API,执行优化器返回的执行计划。
存储引擎:在查询数据的时候,存储引擎会先去buffer pool中查找数据,如果buffer pool中没有,那么才会去读取磁盘上的数据。
-
buffer pool:buffer pool就是MySQL的运行内存,我们查询的数据都是在buffer pool中读取的,如果buffer pool中没有,那么它才去磁盘中读取,buffer pool的基本结构包括:三个双向链表、缓存页(就是MySQL的一页页数据,当然,也有空白页),这三个链表分别是
- FreeList:保存空白缓存页的描述信息,以便于读取数据的时候取用。
- LRUList:已经读到buffer pool中的数据页的描述信息,数据做了冷热隔离,如果buffer pool的空间不够触发了写入磁盘的操作,会优先将冷数据区域的数据写入磁盘中。
- FlushList:存放脏数据页的信息,当我们在MySQL进行数据的修改时,并不是立即将修改后的结果接入磁盘中的,MySQL会将修改的数据页存放在buffer pool中,选择合适的时机写入磁盘,写入完成后就会移除FlushList链表中对应的描述信息。