MySQL一条语句的生命周期


MySQL基本架构

下图是来自MySQL官方的架构图

从上图可以看出,整个mysql整体大致分为几个部分:

  • connectors
  • mysql组件:连接池,优化器,解析器,缓存等
  • 插件式存储引擎,如InnoDB,MyISAM等
  • 文件系统

其中connectors属于客户端与mysql server对接的接口,如JDBC, ODBC等,而文件系统属于硬件基础设施。

MySQL Server主要包含MySQL各个组件以及存储引擎。上图中虽然把文件系统也算在MySQL Server内,但我认为MySQL Server主要是使用了文件系统而已,是否把文件系统给包含进来其实都可以,无关紧要。

SQL执行过程

当我们连接mysql并执行一条语句时,整个过程是怎么样的呢?请看下图:

SQL执行过程

上图中,绿色部分属于MySQL Server。

当执行一条SQL语句时:

  1. 客户端必须先与MySQL Server建立连接,获得授权
  2. 查询缓存,如果缓存中有之前执行过一样的SQL的结果,那么直接返回该结果
  3. 如果没有缓存,则将SQL语句交给分析器进行分析,如果SQL语句不合法,返回错误
  4. 优化器对要执行的SQL进行优化,如选择合适的索引
  5. 将分析并优化过的SQL任务交给执行器进行执行
  6. 存储引擎真正执行数据的存储

以上就是一条SQL语句的整个执行过程

组件

连接池

当我们在客户端执行mysql -u username -p password 时,客户端将会和mysql建立起一个tcp长连接,mysql会对你输入的用户名密码进行校验,并从权限表中查询你的权限。

有时我们启动了一个mysql服务,却发现没法在别的机器远程连接,很有可能因为mysql权限表限制了只能localhost本地连接。

可以查看mysql.user表:

上图中Host为%表示可允许远程连接,如果你的环境只有一条localhost,那么可以使用以下命令将localhost修改为%:

update user set host=’%’ where user=’root’;

或者新建一条记录:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your password' WITH GRANT OPTION;
FLUSH RIVILEGES;

建立连接之后,如果客户端没有发出任何sql给mysql server,那么该连接就会被认为是空闲连接,空闲时间超过8小时,连接将被自动释放。

可以使用以下命令查看空闲释放时间的配置(单位是秒):

mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.00 sec)

查询缓存

MySQL每次查询后,都会将查询结果缓存下来,如果下次查询一样的语句,则会直接使用缓存。但有个严重的问题,一旦数据有更新,缓存将会失效,所以有时候缓存往往会拖累mysql。

因此在mysql8.0,已经将缓存模块直接删除了,所以我们一般不推荐使用查询缓存。可以使用以下配置禁用缓存:

# vi my.cnf
query_cache_type=0
query_cache_size=0

分析器

分析器将会对sql语句做语法分析,词法分析,简单来说就是检查你的语句是否有误,该语句是select还是update,操作的表是哪张表。一旦有误,则直接返回错误

优化器

优化器将对执行方案进行优化,它会决定该语句是否使用索引,使用哪个索引等。我们常用explain命令查看sql语句优化后的执行方案,如:

mysql> explain select * from user;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

执行器

执行器是SQL语句的执行者,不过它本身其实也是调用存储引擎提供的接口进行执行。

存储引擎所提供的接口是比较基础的接口,例如查询一张表的全部数据时,执行器会不断调用储存引擎的接口遍历表数据,直到没有数据为止。而不是直接把整个执行计划丢给存储引擎然后就得到一个结果。

总的来说,存储引擎会提供一些基础的接口,然后执行器根据优化后的执行计划一步步执行整个计划

文章作者: 周君
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 周君 !
评论