你真的了解MySQL吗?MySQL基础架构:一条MySQL查询语句时如何执行的(MySQL的连接器、分析器、优化器、连接器的作用)

提纲

你真的了解MySQL吗?MySQL基础架构:一条MySQL查询语句时如何执行的(MySQL的连接器、分析器、优化器、连接器的作用)_第1张图片

MySQL基础架构

MySQL 可以分为 Server 层和存储引擎层两部分。

  • Server 层
    • 查询缓存、连接器、分析器、优化器、执行器组成。
    • 所有的跨存储引擎功能都在这层实现,如存储过程、触发器、视图
  • 存储引擎
    • 主要负责数据的存储于读取
    • 架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。

你真的了解MySQL吗?MySQL基础架构:一条MySQL查询语句时如何执行的(MySQL的连接器、分析器、优化器、连接器的作用)_第2张图片

 

Server层

连接器

作用

连接器负责跟客户端建立连接、获取权限、维持和管理连接

 

建立连接

mysql -h$ip -P$port -u$user -p

 

权限认证

在完成经典的 TCP 握手后,连接器就要开始认证身份

  • 密码错误:收到"Access denied for user"的错误,然后客户端程序结束执行。
  • 密码正确:读取用户权限。后续所有的权限判断逻辑,都是基于此时获取到的权限进行的
    • 当用户成功建立连接后,即使用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限

 

查询已连接用户

你真的了解MySQL吗?MySQL基础架构:一条MySQL查询语句时如何执行的(MySQL的连接器、分析器、优化器、连接器的作用)_第3张图片

 

连接超时断开

在建立连接后的一段时间,如果客户端没有操作,MySQL服务端将会主动断开连接

  • wait_timeout:默认值是 8 小时

 

长连接带来的内存占用问题

因为建立连接的过程较复杂,我们一般会使用长连接。

MySQL执行过程中使用的临时内存是管理在连接对象中的,只有连接断开后才会被释放。严重的会导致 MySQL 异常重启。

 

解决长连接带来的内存占用问题

  • 定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。
  • 重新初始化连接资源。MySQL 5.7 或更新版本,在每执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。
    • 这个过程不需要重连和重新做权限验证,会将连接恢复到刚刚创建完时的状态。

 

查询缓存

是什么

MySQL 拿到一个查询请求后,会先查缓存,如果命中则直接返回。

 

弊端

每当进行了数据更新操作,查询缓存就会被清空。

  • 对于更新频繁的表来说,将会导致查询缓存的命中率极低
  • 只有在静态表上,才有必要使用查询缓存

 

其他

MySQL 8.0+ 已经删掉了查询缓存

 

分析器

是什么

分析器会对要执行的 SQL 语句进行词法分析和语法分析

 

词法分析

对 SQL 语句中的字符进行解析,解析出其含义。

  • 从 select 关键字识别出来,这是一个查询语句
  • 它要把字符串“T”识别成“表名 T”
  • 把字符串“ID”识别成“列 ID”

 

语法分析

分析输入的 SQL 语句是否符合 MySQL 预发规范

  • 如果语句不对,就会收到“You have an error in your SQL syntax”
mysql> elect * from t where ID=1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'elect * from t where ID=1' at line 1

 

优化器

是什么

优化器会对要执行的 SQL 语句的执行策略进行优化

  • 索引:当包含多个索引时,使用哪个索引
  • join:当多个表连接的时候,绝对各表连接顺序

 

作用

mysql> select * from t1 join t2 using(ID)  where t1.c=10 and t2.d=20;

当多表 JOIN 时候,不同的执行方法逻辑结果是一样,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。

  • 先查询 t1 表, c = 10 的数据,再根据 ID 与 t2 表 join
  • 先查询 t2 表, d = 20 的数据,再根据 ID 与 t1 表 join

 

执行器

作用

通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。

 

执行过程

  • 判断执行权限
mysql> select * from T where ID=10;

ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'
  • 调用执行引擎接口,执行 SQL 语句
    • 调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 10,如果不是则跳过,如果是则将这行存在结果集中
    • 调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行
    • 执行器将上述遍历过程中所有满足条件的行组成的记录集,作为结果集返回给客户端。
    • 如果表存在索引,则执行步骤有些许不同

调用 InnoDB 引擎接口取这个表的第一行 -> 取这个表,满足条件的第一行

  • 调用引擎接口取“下一行” -> 调用引擎接口取“满足条件的下一行

 

rows_examined

数据库的慢查询日志中看到一个 rows_examined 的字段,表示这个语句执行过程中扫描了多少行。

  • 这个值是在执行器每次调用引擎获取数据行的时候累加的(并不是执行引擎扫描了多少航)
    • 换句话说,就是执行器调用执行引擎获取数据行的次数
  • 在有些场景下,执行器调用一次,在引擎内部则扫描了多行、因此执行引擎扫描行数跟 rows_examined 并不是完全相同

你可能感兴趣的:(数据库)