mysql 命令与sqlserver的区别大么

MySQL系列之执行SQL 语句时发生了什么?

mysql 命令与sqlserver的区别大么(MySQL系列之执行SQL 语句时发生了什么?)

前言

 

当我们用 navicat、mysql workbench 等mysql 的客户端执行一条sql语句后,我们就能得到相应的结果。例如:

mysql 命令与sqlserver的区别大么(MySQL系列之执行SQL 语句时发生了什么?)

那么这个过程发生了什么呢?

执行一条sql 就是一次Rpc的调用

 

mysql 是一个客户端、服务端的架构。我们平时使用的大部分程序app其实是由两部分组成的,一部分是客户端程序,一部分是服务器程序。

以我们常用的微信、qq 为例。我们手机里面装的客户端,机房的服务器中运行着server端。我们平时发信息都是其实都是用客户端和服务端打交道。比如你和你女朋友发信息的过程:

  1. 消息被客户端包装了一下,添加了发送者和接收者信息,然后从你的微信客户端传送给微信服务器;
  2. 微信服务器从消息里获取到它的发送者和接收者,根据消息的接收者信息把这条消息送达到你女朋友的微信客户端,你女朋友的微信客户端里就显示出你给他发了一条消息。

mysql的使用过程跟这个是一样的,它的服务器程序直接和我们存储的数据打交道,然后可以有好多客户端程序连接到这个服务器程序,发送增删改查的请求,然后服务器就响应这些请求,从而操作它维护的数据。

主要流程如下:

mysql 命令与sqlserver的区别大么(MySQL系列之执行SQL 语句时发生了什么?)

所以,一条sql的执行,就是一次rpc的调用。后面有时间也会分享RPC 相关的东西,一起交流学习!

服务器怎么处理客户端请求

 

不管我们用了哪种客户端和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。主要过程如下:

mysql 命令与sqlserver的区别大么(MySQL系列之执行SQL 语句时发生了什么?)

从图中我们可以看出,服务器程序处理来自客户端的查询请求大致需要经过三个部分,分别是 连接管理、解析优化与执行、存储引擎三个部分。其中连接管理、解析优化与执行常常被分为mysql的 server 层。

连接管理

 

客户端进程可以采用TCP/IP、命名管道或共享内存、Unix域套接字这几种方式之一来与服务器进程建立连接。

对连接的管理也使用了池化技术:每当有一个客户端进程连接到服务器进程时,服务器进程都会创建一个线程来专门处理与这个客户端的交互,当该客户端退出时会与服务器断开连接,服务器并不会立即把与该客户端交互的线程销毁掉,而是把它缓存起来,在另一个新的客户端再进行连接时,把这个缓存的线程分配给该新客户端。这样就起到了不频繁创建和销毁线程的效果,从而节省开销。

查询缓存

 

由于表经常更新,查询缓存的失效频繁,查询缓存往往利大于弊。,MySQL 8.0 版本开始直接将查询缓存的整块功能删掉了。

语法解析

 

如果查询缓存没有命中,接下来就需要进入正式的查询阶段了。因为客户端程序发送过来的请求只是一段文本而已,所以MySQL服务器程序首先要对这段文本做分析,判断请求的语法是否正确,然后从文本中将要查询的表、各种查询条件都提取出来放到MySQL服务器内部使用的一些数据结构上来。

查询优化

 

经过了语法解析,MySQL 就知道你要做什么了。在开始执行之前,还要先经过查询优化的处理。优化处理是指在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。我们可以使用EXPLAIN语句来查看某个语句的执行计划 。

大部分优化的逻辑是基于成本的优化。在MySQL中一条查询语句的执行成本是由两个方面组成的 :

对于InnoDB存储引擎来说 ,mysql规定读取一个页面花费的成本默认是1.0,读取以及检测一条记录是否符合搜索条件的成本默认是0.2 。

拿单表查询来举例,成本计算步骤如下:

存储引擎

 

执行器

 

执行器就是各种不同的存储引擎向上边的MySQL server层提供统一的调用接口(也就是存储引擎API),包含了几十个底层函数,像"读取索引第一条内容"、"读取索引下一条内容"、"插入记录"等等。

比如执行一条查询sql 时,开始执行的时候,要先判断一下你对这个表 有没有执行查询的权限,如果没有,就会返回没有权限的错误;

拿我们开头的例子中,id字段没有索引,那么执行器的执行流程是这样的:

对于有索引的表,执行的逻辑也差不多。第一次调用的是“取满足条件的第一行”这个接口,之后循环取“满足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。但是对于 插入、删除和修改的sql语句,还要涉及到redolog、undolog 和binlog 的操作。这个我们有空再聊。

所以只需按照生成的执行计划调用底层存储引擎提供的API(执行器),获取到数据后返回给客户端就好了。一条sql 语句就执行完成了。

原文链接:https://www.toutiao.com/i6966889099424694796/