MySQL(二):一条SQL查询语句的执行过程

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、参考文献

  1. 《高性能MySQL(第3版)》
  2. 《MySQL技术内幕:InnoDB存储引擎(第2版)》
  3. 《MySQL源码库》
  4. 《MySQL参考手册》
  5. 《MySQL实战45讲》
  6. 《MySQL 是怎样运行的:从根儿上理解 MySQL》
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要查询最近一条记录,可以使用ORDER BY和LIMIT子句。下面是MySQL中查询最近一条记录的SQL语句: SELECT * FROM 表名 ORDER BY id DESC LIMIT 1; 其中,"表名"是要查询的数据库表的名称,"id"是表中的唯一标识列。通过将结果按id列的降序排列,可以将最新记录放在结果集的第一行。使用LIMIT 1可以限制结果集只返回一条记录。这样即可查询到最近的一条记录。 注意,上述语句中的id列是假设的列名,实际使用时需要根据具体的表结构来替换。另外,如果想要查询表中的特定字段而不是所有字段,可以将"*"替换为字段名称。 ### 回答2: 要查询最近一条记录的SQL语句,可以使用以下代码: SELECT * FROM 表名 ORDER BY id DESC LIMIT 1; 在上述代码中,需要将"表名"替换为你想要查询的表的实际名称。这条SQL语句的执行过程如下: 首先,使用SELECT *从表中选取所有的列。 然后,通过使用ORDER BY id DESC将结果按照id列的降序排序,这意味着最新的记录将位于最前面。 最后,通过使用LIMIT 1限制结果集的大小只为1,从而仅返回最新的一条记录。 这样,就可以通过这条SQL语句查询到最近的一条记录。 ### 回答3: 要查询最近一条记录,可以使用以下的SQL语句: ``` SELECT * FROM 表名 ORDER BY 时间列名 DESC LIMIT 1; ``` 其中,表名是你要查询的表的名称,时间列名是表中记录时间的列名。 这个查询语句的作用是首先通过`ORDER BY`子句将记录按照时间列名降序排列,最近的记录排在第一位。然后使用`LIMIT`关键字限制查询结果只返回第一条记录,即最近的一条记录。 例如,如果我们有一个存储员工信息的表employee,其中有一个记录时间的列叫做create_time,我们可以使用以下的SQL语句查询最近一条记录: ``` SELECT * FROM employee ORDER BY create_time DESC LIMIT 1; ``` 这个查询语句会返回employee表中最近插入的一条记录的所有字段信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值