MySQL(二):一条SQL查询语句的执行过程
文章目录
- 1、简述
- 2、SQL 的执行过程
- 2.1、连接器
- 2.1.1、通信方式
- 2.1.2、TCP/IP
- 2.1.3、命名管道和共享内存
- 2.1.4、Unix域套接字
- 2.2、查询缓存
- 2.2.1、缓存条件
- 2.2.2、缓存失效
- 2.3、语法解析器
- 2.4、查询优化器
- 2.5、执行器
- 3、参考文献
1、简述
MySQL是怎样运行的?本文就从一条查询SQL在MySQL的执行过程来拆解一下都经过了那些流程处理,以加深我们对MySQL的理解。然后在我们的工作中可以稍微多思考一点,那么当我们再次碰到MySQL的一些异常时,就能更准确快速的定位问题并解决问题。
select username from t_user where id=1
当我们向MySQL提交一条这样简单的SQL语句,MySQL是如何处理的呢?答案请看下图,下面我们就根据下图一步一步跟随这条MySQL走一下执行流程。
2、SQL 的执行过程
2.1、连接器
2.1.1、通信方式
在了解连接器之前,我们有必要先了解一下MySQL客户端与MySQL服务端的通信方式,MySQL客户端与服务端的所用通信都要使用以下通信协议的一种进行通信。
这里需要注意一下,这里所说的MySQL客户端并不是我们应用程序中引用的MySQL JDBC Driver。实际上MySQL服务端程序和客户端程序本质上都是计算机上的一个进程,所以客户端进程向服务端进程发送请求并得到回复的过程本质上是一个进程间通信的过程。
MySQL提供的通信方式有以下几种:
2.1.2、TCP/IP
在实际应用中,数据库服务器进程和客户端进程可能运行在不同的主机中,它们之间必须通过网络来进行通讯。MySQL采用TCP/IP套接字作为服务器和客户端之间的网络通信协议。例如我们可以在本机的Windows下请求一台远程Linux环境下的一台MySQL实例:
D:\Java\mysql-8.0.17-winx64\bin> mysql -h192.168.10.89 -uroot -p
Enter password: ****
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 8.0.17 MySQL Community Server - GPL
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
这里的客户端就是本机Windows,服务端就是远程Linux下的MySQL实例,客户端向服务端发起TCP请求,并且连接成功,然后就可以进行一些DDL或DML操作了。
2.1.3、命名管道和共享内存
在Windows上,如果两个需要通信的进程在同一个机器上,那么客户端进程和服务器进程之间可以使用命名管道进行通信。
在MySQL中要使用命名管道和共享内存时需要在配置文件或命令中添加一些参数:
1、使用命名管道来进行进程间通信
需要在MySQL服务端配置文件中启用–enable-named-pipe参数,然后在客户端命令中加入–pipe或者–protocol=pipe参数。
2、使用共享内存来进行进程间通信
需要在MySQL服务端配置文件中启用–shared-memory参数,如果使用共享内存的连接方式,需要在客户端程命令中加入–protocol=memory 参数来显式的指定使用共享内存进行通信。
2.1.4、Unix域套接字
在Linux和unix环境下可以使用Unix域套接字来实现进程间通信。前提这要求服务端进程和客户端进程都运行在同一台机器上。首先在服务端配置文件上启用 —protocol=socket 参数,并指定套接字文件路径 —socket=/tmp/mysql.sock,这是默认路径,如果修改了路径,我们可以使用以下命令查找套接字文件的路径。
mysql> show variables like 'socket';
+---------------+-----------------------------+
| Variable_name | Value |
+---------------+-----------------------------+
| socket | /var/run/mysqld/mysqld.sock |
+---------------+-----------------------------+
使用Unix域套接字文件登录:
root@477f524b9210:/etc/mysql# mysql -hlocalhost -uroot -S /var/run/mysqld/mysqld.sock -p;
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12855
Server version: 8.0.18 MySQL Community Server - GPL
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
2.2、查询缓存
MySQL 查询缓存保存了查询返回的完整结果。当查询命中该缓存时,MySQL会立即返回结果,也就跳过了解析、优化和执行阶段。
MySQL 将缓存存放在一个引用表中,通过一个哈希值引用,这个哈希值包括了以下因素,即查询本身、当前要查询的数据库、客户端协议的版本等一些其他可能影响返回结果的信息。
如果第二次查询的SQL和第一次查询的SQL完全相同(必须是完全相同,即使多一个空格或者大小写不同都认为不同)且开启了查询缓存,那么第二次查询就直接从查询缓存中取结果。
2.2.1、缓存条件
当查询语句中有一些不确定的数据时,则不会被缓存,例如包含系统函数、用户自定义变量和函数、系统表如 mysql 、information_schema、 performance_schema 数据库中的表
的查询不会被缓存。
2.2.2、缓存失效
查询缓存系统会跟踪查询中涉及的每个表,如果这些表的结构或数据发生了改变(INSERT、 UPDATE、DELETE、TRUNCATE TABLE、ALTER TABLE、DROP TABLE或 DROP DATABASE),那么和这个表相关的所有缓存数据都将失效。
2.3、语法解析器
如果没有命中缓存,就需要开始执行 sql 语句了,在执行之前需要先对 sql 语句进行解析。
语法解析器主要对 sql 语句进行语法和语义分析,检查单词是否拼写错误,检查要查询的表或字段是否存在。
2.4、查询优化器
语法解析之后,服务程序就知道了要查询那些列,哪些表,查询条件等等。下一步,MySQL的优化程序会对我们的语句做一些优化,如外连接转换为内连接、表达式简化、子查询转为连接等。优化的结果就是生成一个执行计划,这个执行计划表明了应该使用哪些索引进行查询,表之间的连接顺序等。我们可以使用 EXPLAIN 语句来查看某个语句的执行计划。
2.5、执行器
在完成了sql语句优化之后,MySQL 执行器就会根据执行计划调用底层存储引擎提供的API去执行数据的检索,获取到数据后返回给客户端整个流程就借宿了。
本文通过一条简单的 Sql 语句,梳理了 sql 的整个执行过程,我们大概也了解了MySQL的几个重要组件。接下来的文章中会对各个组件进行详细的阐述和介绍,本文暂不做深入的学习。
3、参考文献
- 《高性能MySQL(第3版)》
- 《MySQL技术内幕:InnoDB存储引擎(第2版)》
- 《MySQL源码库》
- 《MySQL参考手册》
- 《MySQL实战45讲》
- 《MySQL 是怎样运行的:从根儿上理解 MySQL》
还没有评论,来说两句吧...