首先咱们来了解 MySQL 的逻辑架构,对 MySQL 有一个总体的认识。mysql
例如在执行下面的一条语句时:sql
mysql> select * from T where ID=10;
咱们看到的结果是返回一条记录,那么 MySQL 是如何执行这条 SQL 查询语句呢?缓存
首先咱们来看一下 MySQL 的逻辑架构图:架构
大致来讲,MySQL 分为 Server 层和存储引擎层两部分。优化
Server 层包含链接器、查询缓存、分析器、优化器、执行器等 MySQL 的核心服务功能。插件
存储引擎层负责数据的存储和提取。其架构是插件式的,支持 InnoDB、MyISAM、Memory 等多种存储引擎。code
从图中不难看出,不一样的存储引擎共用一个 Server 层。下面咱们经过上面那条 SQL 查询语句来看一下总体流程和每一个组件的做用。server
链接器是客户端与 MySQL 进行链接的组件。客户端经过如下命令进行链接:blog
mysql -h$ip -P$port -u$user -p
输完这条命令后,再输入用户名和密码。虽然也可以在上面的命令里同时输入密码,但容易形成密码泄露,尤为是在生产环境中,不建议把密码显式输入。索引
这意味着,一个用户成功创建链接后,即使修改了他的权限,当前链接也不会生效,除非断开重连。
上一步与 MySQL 创建了链接,而后咱们从客户端输入 SQL 查询语句:
mysql> select * from T where ID=10;
MySQL 会先到查询缓存里找,看是否存在这条记录。若是存在,则直接返回结果。
可是大多数状况下我会建议你不要使用查询缓存,为何呢?由于查询缓存每每弊大于利。
查询缓存里的缓存数据很容易失效,只要表中任意数据的更新都会清空这个表的缓存,尤为是对于写比较频繁的应用,缓存基本不起效果。
咱们能够经过把参数 query_cache_type
设置成 DEMAND
来禁用查询缓存,也能够显式设置使用查询缓存:
mysql> select SQL_CACHE * from T where ID=10;
注意:MySQL 8.0 版本直接将查询缓存的整块功能删掉了,也就是说 8.0 开始完全没有这个功能了。
MySQL 是如何 “认得出” 这条 SQL 语句的呢?
经过分析器,MySQL 首先对 SQL 语句进行词法分析,提取为若干个字符串。
而后再进行语法分析,判断 SQL 语句是否符合 MySQL 的语法。
若是你的语句不对,就会收到 “You have an error in your SQL syntax” 的错误提醒,好比下面这个语句 select 少打了开头的字母 “s” 。
mysql> elect * from t where ID=1; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'elect * from t where ID=1' at line 1
通常语法错误会提示第一个出现错误的位置,因此你要关注的是紧接 “use near” 的内容。
通过分析器,MySQL 知道了要作什么,在开始执行前,还须要通过优化器的处理。
优化器是在表里有多个索引时,决定使用哪一个索引。好比下面的查询语句:
mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
有两种执行方式:
t1.c=10
的行,而后再从表 t2 里判断 t1.ID=t2.ID and t2.d=20
。t2.d=20
的行,而后再从表 t1 里判断 t1.ID=t2.ID and t1.c=10
。优化器就是判断要选择哪一种执行方式,大概的判断依据是 “成本估算”,估算哪一种执行方式的 “成本” 更低,就选择哪一种。
MySQL 通过分析器知道要作什么,通过优化器知道怎么作,最后就是执行了。首先 MySQL 会判断是否具备查询权限,若是没有,就返回没有权限的错误,以下:
mysql> select * from T where ID=10; ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'
若是有权限,就打开表继续执行。打开表的时候,执行器会根据表中定义的存储引擎,去使用这个存储引擎提供的接口。
好比咱们的例子中,表 T 中,ID 字段没有索引,那么执行器的流程是:
ID=10
。若是不是,则跳过;如是,则保存到结果集中。