美文网首页
MySql那些事—基础架构

MySql那些事—基础架构

作者: Dane_404 | 来源:发表于2019-11-13 21:41 被阅读0次

本篇的目的是,从一条查询语句,学习下MySql内部的执行过程,对MySql的基础架构有一个大致的认识。

基础架构图

image

大体来说,MySQL可以分为Server 层和存储引擎层两部分。

Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。

而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。

从图中不难看出,不同的存储引擎共用一个 Server 层,也就是从连接器到执行器的部分。

连接器

连接器也就是平时开发中连接数据库这一过程,比如:

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

然后再输入密码,虽然有可以直接把密码跟在-p后面,但强烈建议你不要这么做,因为密码跟在-p后面是明文的,这样可能导致密码泄露。

连接器这个阶段先是验证用户名密码,当用户名和密码验证成功后,连接器会进一步验证权限,之后,这个连接里面所有的权限判断逻辑,都是依赖于此时读到的权限。所以,这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。

连接完成后,如果没有后续操作,这个连接就为空闲状态,标价为sleep,客户端如果太长时间没动静,超过了wait_timeout的时间(默认是8h),连接器就会自动断开连接。

我们平时都知道,频繁的连接断开是很耗性能的,所以都是尽量长连接,但全部使用长连接后,可能会发现MySql内存占用涨得特别快,这是因为MySql在执行过程中临时使用的内存是管理在连接对象里面的,这些资源会在连接断开的时候才释放,所以,如果长连接积累下来,可能导致内存占用太大,OOM被系统杀掉了。

针对长连接的问题:

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

查询缓存

MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果。如果你的查询能够直接在这个缓存中找到 key,那么这个 value 就会被直接返回给客户端。

如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。

但是查询缓存弊大于利,查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。因此很可能你费劲地把结果存起来,还没使用呢,就被一个更新全清空了。对于更新压力大的数据库来说,查询缓存的命中率会非常低。除非你的业务就是有一张静态表,很长时间才会更新一次。比如,一个系统配置表,那这张表上的查询才适合使用查询缓存。

在MySQL8.0之前,可以将参数 query_cache_type 设置成 DEMAND,需要缓存的时候可以使用SQL_CACHE,如:

select SQL_CACHE * from T where ID=10

MySQL8.0开始,查询缓存整个功能都删掉了

分析器

从这里开始真正的执行语句了

首先,MySQL需要知道你想要干什么,因此需要对SQL语句做解析,比如说,识别到select,知道是个查询语句,user知道是表,id知道是列,做完这些识别后,就会进行语法分析,判断是否满足MySQL语法。

优化器

优化器是在表里面有多个索引的时候,决定使用哪个索引,或者在一个语句有多表关联的时候,决定各个表的连接顺序,所以优化器的作用就是决定选择使用哪一种方案。

执行器

开始执行的时候,会先判断对这个表有没有执行查询权限,没有则返回权限错误,如果有就会打开表继续执行,打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。

比如查询表T,如果是没有索引,那么执行器的执行流程是这样的:

  • 调用InnoDB引擎接口取这个表的第一行,满足查询语句的就将存在结果集中,然后继续下一行,直到读完整个表。
  • 读取完成后,将结果集返回给客户端。

若是有索引的情况,执行逻辑差不多,就是只读取满足条件的行数。

数据库查询日志中有个row_examined字段,是表示这个语句执行过程中扫描了多少行,不过在有些场景下,执行器调用一次,在引擎内部却扫描了多行,因此引擎扫描行数跟row_examined并不是完全相同的。

相关文章

网友评论

      本文标题:MySql那些事—基础架构

      本文链接:https://www.haomeiwen.com/subject/qpgkictx.html