MySQL(一)SQL执行流程与MySQL架构

目录

MySQL语句的执行流程

1.通信协议

1.1通信协议

1.2 通信方式

2.查询缓存

3.语法解析和预处理

3.1 词法解析

3.2 语法解析

3.3 预处理器

4.查询优化(Query Optimizer)与执行计划

5.存储引擎

6. 执行引擎,返回结果

MySQL体系结构


MySQL语句的执行流程

当向MySQL发送一条SQL请求的时候,MySQL到底进行了如下步骤:

  • 客户端与服务器建立连接,发送语句。
  • 服务器先查询缓存,如果命中了缓存,则立刻返回缓存中的结果。
  • 如果没有缓存,则服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划。
  • MySQL根据优化器生成的执行计划,调用存储引擎的API来执行。
  • 将结果返回给客户端。

具体过程如下

1.通信协议

首先,MySQL必须要运行一个服务,监听默认的3306端口

1.1通信协议

MySQL是支持多种通信协议的,可以使用同步/异步的方式,支持长连接/短连接

通信类型:同步或者异步

同步通信的特点:
1.同步通信依赖于被调用方,受限于被调用方的性能。也就是说,应用操作数据库,线程会阻塞,需要等待数据库的返回。
2.一般只能做到一对一,很难做到一对多的通信。
异步跟同步相反:
1.异步可以避免应用阻塞等待,但是SQL执行的时间不能节省
2.如果异步存在并发,每一个SQL的执行都要单独建立一个连接,避免数据混乱。
但是这样会给服务端带来巨大的压力(一个连接就会创建一个线程,线程间切换会占用大量CPU资源)。另外异步通信还带来了编码的复杂度,所以一般不建议使用。如果要使用异步,必须使用连接池,排队从连接池获取连接而不是每次创建新连接
一般来说我们连接数据库都是使用的同步连接。

连接方式:长连接或者短连接

MySQL既支持短连接,也支持长连接。短连接就是操作完毕以后,马上关掉连接,长连接可以保持打开,减少服务端创建和释放连接的消耗,后面的程序访问的时候还可以使用这个连接。一般我们会在连接池中使用长连接。
保持长连接会消耗内存。长时间不活动的连接,MySQL服务器会断开

show global variables like 'wait_timeout'; -- 非交互式超时时间,如 JDBC 程序
show global variables like 'interactive_timeout'; -- 交互式超时时间,如数据库工具

#查看MySQL当前有多少个连接?
show global status like'Thread%';
#查看SQL的执行状态
SHOW PROCESSLIST; 

一些常见的状态: https://dev.mysql.com/doc/refman/5.7/en/thread-commands.html

MySQL以下两种通信协议:
1.Unix Socket
比如我们在Linux服务器上,如果没有指定-h参数,它就用socket方式登录(省略了-S /var/lib/mysql/mysql.sock)。
不用通过网络协议,也可以连接到MySQL的服务器,它需要用到服务器上的一个物理文件(/var/lib/mysql/mysql.sock)。
2.如果指定-h参数,就会用第二种方式,TCP/IP协议
mysql -h 192.168.56.10 -u root -p 123456
我们的编程语言的连接模块都是用 TCP 协议连接到 MySQL 服务器的,比如mysql-connector-java-x.x.xx.jar。

1.2 通信方式

 mysql客户端和服务器之间的通讯协议是“半双工”的,这意味着,在任何一个时刻,要么由服务器向客户端发送数据,要么由客户端向服务器发送数据,这两个动作不能同时发生。这种协议让mysql通信简单快速,但也限制了mysql。一个明显的限制是,这意味着没办法进行流量限制。一旦一端开始发生消息,另一端要接收完整个消息才能响应。

如果SQL语句里的内容非常多,比方说一个批量的插入语句,这个时候我们就要调整MySQL服务器配置max_allowed_packet参数的值(默认是4M),把它调大,否则就会报错。
另一方面,对于服务端来说,也是一次性发送所有的数据,不能因为你已经取到了想要的数据就中断操作,这个时候会对网络和内存产生大量消耗。
所以,我们一定要在程序里面避免不带limit 的这种操作,比如一次把所有满足条件的数据全部查出来,一定要先count一下。如果数据量大的话,可以分批查询。

2.查询缓存

MySQL内部自带了一个缓存模块。
MySQL的缓存默认是关闭的。因为MySQL的缓存是不推荐使用,主要是因为MySQL自带的缓存的应用场景有限。

第一个是它要求SQL语句必须一模一样,中间多一个空格,字母大小写不同都被认为是不同的的SQL。
第二个是表里面任何一条数据发生变化的时候,这张表所有缓存都会失效,所以对于有大量数据更新的应用,也不适合

3.语法解析和预处理

这一步主要做的事情是对语句基于SQL语法进行词法和语法分析和语义的解析。

3.1 词法解析

词法分析就是把一个完整的SQL语句打碎成一个个的单词。

比如一个SQL:select name from user where id=1;会打碎成8个词语,每个词语从哪里开始到哪里结束

3.2 语法解析

语法分析会对SQL做一些语法检查,比如单引号有没有闭合,然后根据MySQL定义的语法规则,根据SQL语句生成一个数据结构-----解析树

3.3 预处理器

如果执行一个词法和语法都正确的SQL,但是表名或者字段不存在,预处理器会帮助我们判断这些错误,直接返回

它会检查生成的解析树,解决解析器无法解析的语义。比如,它会检查表和列名是否存在,检查名字和别名,保证没有歧义。
预处理之后得到一个新的解析树

4.查询优化(Query Optimizer)与执行计划

查询优化器会将解析树转化成执行计划。一条查询可以有多种执行方法,最后都是返回相同结果。优化器的作用就是找到这其中最好的执行计划。

MySQL里面使用的是基于开销(cost)的优化器,那种执行计划开销最小,就用哪种。

比方说:
当我们对多张表进行关联查询的时候,以哪个表的数据作为基准表;当有多个索引可以使用的时候,选择哪个索引。

优化器最终会把解析树变成一个查询执行计划,查询执行计划是一个数据结构。
当然,这个执行计划也不一定是最优的执行计划,因为MySQL也有可能覆盖不到所有的执行计划

我们在SQL语句前面加上EXPLAIN,就可以看到执行计划的信息。
EXPLAIN select name from user where id=1;
注意Explain的结果也不一定最终执行的方式。

5.存储引擎

在关系型数据库里面,数据是放表Table里面的
我们可以把这个表理解成Excel电子表格的形式。所以我们的表在存储数据的同时,还要组织数据的存储结构,这个存储结构就是由我们的存储引擎决定的,所以我们也可以把存储引擎叫做表类型

在MySQL里面,支持多种存储引擎,他们是可以替换的,所以叫做插件式的存储引擎
我们创建的每一张表都可以指定它的存储引擎,存储引擎的使用是以表为单位的。而且,创建表之后还可以修改存储引擎
通过如下命令我们可以知道数据库的数据是存储在什么目录下的


每个数据库有一个自己文件夹,任何一个存储引擎都有一个frm文件,这个是表结构定义文件。不同的存储引擎存放数据的方式不一样,产生的文件也不一样,innodb 是 1 个,memory没有,myisam是两个。

MyISAM 和InnoDB 是我们用得最多的两个存储引擎,在 MySQL 5.5.5 版本之前,默认的存储引擎是MyISAM,它是MySQL自带的。5.5.5版本之后默认的存储引擎改成了InnoDB,它是第三方公司为MySQL开发的。
修改默认的存储引擎的最主要原因还是因为InnoDB 支持事务,支持行级别的锁,对于业务一致性要求高的场景来说更适合

不同的存储引擎的特性:https://dev.mysql.com/doc/refman/5.7/en/storage-engines.html

MyISAM(3 个文件)

Thesetableshaveasmallfootprint.Table-levellockinglimitstheperformanceinread/writeworkloads,soitisoftenused inread-onlyorread-mostlyworkloadsinWebanddatawarehousingconfigurations. 

特点:
支持表级别的锁(插入和更新会锁表)。不支持事务。
拥有较高的插入(insert)和查询(select)速度。
存储了表的行数(count速度更快)。

InnoDB(2 个文件)

特点:
支持事务,支持外键,因此数据的完整性、一致性更高。
支持行级别的锁和表级别的锁。
支持读写并发,写不阻塞读(MVCC)。
特殊的索引存放方式,可以减少IO,提升查询效率。
适合:经常更新的表,存在并发读写或者有事务处理的业务系统。

Memory(1 个文件)

Stores all data in RAM, for fast access in environments that require quick lookups of non-critical data. This engine was formerly known as the HEAP engine. Its use cases are decreasing; InnoDB with its buffer pool memory area provides a general-purpose and durable way to keep most or all data in memory, and NDBCLUSTER provides fast key-value lookups for hugedistributeddatasets. 

把数据放在内存里面,读写的速度很快,但是数据库重启或者崩溃,数据会全部消失。只适合做临时表。

CSV(3 个文件)

Its tables are really text files with comma-separated values. CSV tables let you import or dump data in CSV format, to exchange data with scripts and applications that read and write that same format. Because CSV tables are not indexed, you typically keep the data in InnoDB tables during normal operation, and only use CSV tables during the import or export stage.

它的表实际上是带有逗号分隔值的文本文件。因为csv 表没有索引,所以通常在正常操作期间将数据保存在innodb表中,并且只在导入或导出阶段使用csv表。
特点:
不允许空行,不支持索引。格式通用,可以直接编辑,适合在不同数据库之间导入导出。

Archive(2 个文件)

These compact, unindexed tables are intended for storing and retrieving large amounts of seldom-referenced historical, archived,orsecurityauditinformation. 

这些紧凑的未使用索引的表用于存储和检索大量很少引用的历史、存档或安全审计信息。
特点:不支持索引,不支持update delete

存储引擎的选择:

如果对数据一致性要求比较高,需要事务支持,可以选择InnoDB。
如果数据查询多更新少,对查询性能要求比较高,可以选择MyISAM。
如果需要一个用于查询的临时表,可以选择Memory。

6. 执行引擎,返回结果

我们的执行引擎使用执行计划去操作存储引擎,它利用存储引擎提供的相应API来完成操作。
不同功能的存储引擎实现的API是相同的
最后把数据返回给客户端,即使没有结果也要返回。


MySQL体系结构

1.Connector:用来支持各种语言和SQL的交互,比如PHP,Python,Java的JDBC等;
2.Management Serveices & Utilities:系统管理和控制工具,包括备份恢复、MySQL复制、集群等;
3.Connection Pool:连接池,管理需要缓冲的资源,包括用户密码,权限,线程等等;
4.SQL Interface:用来接收用户的SQL命令,返回用户需要的查询结果
5.Parser:用来解析SQL语句;
6.Optimizer:查询优化器;
7.Cache and Buffer:查询缓存,除了行记录的缓存之外,还有表缓存,Key缓存,权限缓存等等;
8.Pluggable Storage Engines:插件式存储引擎,它提供API给服务层使用,跟具体的存储文件打交道

总体上,我们可以把MySQL分成三层,跟客户端对接的连接层,真正执行操作的服务层,和跟硬件打交道的存储引擎层

连接层
客户端要连接到MySQL服务器3306端口,必须要跟服务端建立连接,那么管理所有的连接,验证客户端的身份和权限,这些功能就在连接层完成。

服务层
连接层会把SQL语句交给服务层,这里面又包含一系列的流程:比如查询缓存、根据SQL调用相应的接口,对我们的SQL语句进行词法和语法的解析(比如关键字,别名怎么识别,语法有没有错误等)。然后就是优化器,MySQL底层会根据一定的规则对我们的 SQL语句进行优化,最后再交给执行器去执行

存储引擎
存储引擎就是我们的数据真正存放的地方,在MySQL里面支持不同的存储引擎。再往下就是内存或者磁盘。
 

发布了47 篇原创文章 · 获赞 12 · 访问量 5060

猜你喜欢

转载自blog.csdn.net/qq_35448165/article/details/104158657