MySQL提高笔记(1):MySQL逻辑架构

深刻学习MySQL,从概览MySQL逻辑架构开始。mysql

首先来看一下MySQL的逻辑架构图:sql

MySQL逻辑架构

MySQL逻辑架构大概能够分为三层:数据库

  • 客户端:最上层的服务并非MySQL所独有的,大多数基于网络的客户端/服务器的工具或者服务都有相似的架构。好比链接处理、受权认证、安全等等。
  • Server层:大多数MySQL的核心服务功能都在这一层,包括查询解析、分析、优化、缓存以及全部的内置函数(例如,日期、时间、数学和加密函数),全部跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。
  • 存储引擎层:第三层包含了存储引擎。存储引擎负责MySQL中数据的存储和提取。Server层经过API与存储引擎进行通讯。这些接口屏蔽了不一样存储引擎之间的差别,使得这些差别对上层的查询过程透明。

值得一提的是在MySQL8.0中取消了查询缓存,大概的理由是查询缓存存在严重的可伸缩性问题,而且很容易成为严重的瓶颈缓存,将缓存移动到客户端能收获更好的性能。缓存

MySQL查询缓存

经过一条查询语句的执行过程,来了解一些关键的部件:安全

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;
  • 既能够先从表t1里面取出c=10的记录的ID值,再根据ID值关联到表t2,再判断t2里面d的值是否等于20。
  • 也能够先从表t2里面取出d=20的记录的ID值,再根据ID值关联到t1,再判断t1里面c的值是否等于10。

这两种执行方法的逻辑结果是同样的,可是执行的效率会有不一样,而优化器的做用就是决定选择使用哪个方案。

优化器阶段完成后,这个语句的执行方案就肯定下来了,而后进入执行器阶段。若是你还有一些疑问,好比优化器是怎么选择索引的,有没有可能选择错等等,不要紧,我会在后面的文章中单独展开说明优化器的内容。

五、执行器

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. 调用InnoDB引擎接口取这个表的第一行,判断ID值是否是10,若是不是则跳过,若是是则将这行存在结果集中;
  2. 调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
  3. 执行器将上述遍历过程当中全部知足条件的行组成的记录集做为结果集返回给客户端。

至此,这个语句就执行完成了。

对于有索引的表,执行的逻辑也差很少。第一次调用的是“取知足条件的第一行”这个接口,以后循环取“知足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。




参考:

【1】:《高性能MySQL》

【2】:极客时间 《MySQL实战45讲》

【3】:《MySQL技术内幕 InnoDB存储引擎》

【4】:MySQL 8.0: Retiring Support for the Query Cache

【5】:头条二面: 详解一条 SQL 的执行过程

相关文章
相关标签/搜索