丁奇mysql实战45讲(一)笔记

一.概述

[1.基础架构:一条SQL查询语句是如何执行的?]
Mysql可以分为Server层和存储引擎两部分

下面的是mysql的逻辑架构图

img

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

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

补充:(插件式的架构模式)

插件(Plugin)模式向用户提供了一种扩展程序的接口,用户可以在程序本体之外,按照指定接口编写插件来为程序增加功能。

img

二.Server层组件介绍

以下面这句sql语句为例,看看sql语句是如何执行的

select * from T where ID=10

1.连接器

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

②连接命令如下,密码虽然可以直接跟在-p后面,但是会造成密码泄露所以不要这样做,输入下面的命令后会额外让你输入密码

mysql -h$ip -P$port -u$user -p
  • 如果用户名或密码不对,你就会收到一个"Access denied for user"的错误,然后客户端程序结束执行。
  • 如果用户名密码认证通过,连接器会到权限表里面查出你拥有的权限。之后,这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。

(获取权限这点尤其注意一下,因为在连接器处获取权限,所以后面管理员就算进行了权限修改,不能立即生效,要等下次连接的时候才能生效)

③连接完成后,如果你没有后续的动作,这个连接就处于空闲状态,你可以在 show processlist 命令中看到它。文本中这个图是 show processlist 的结果,其中的 Command 列显示为“Sleep”的这一行,就表示现在系统里面有一个空闲连接。

img

其中wait_timeout这个值控制最大空闲时间,默认8小时,超过这个时间连接会自动断开,自动断开连接后要重连才能成功发送请求

img

④数据库中长连接和短连接的概念

  • 长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。
  • 短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。

因为建立数据库连接较为复杂,一般建议尽量使用长连接

但使用长连接非常占用内存,这是因为 MySQL 在执行过程中临时使用的内存是管理在连接对象里面的。这些资源会在连接断开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是 MySQL 异常重启了。

解决方案:

①定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。

②如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。

2.查询缓存

(mysql8.0已经删除了查询缓存,这部分了解一下就好)

2.1.在mysql拿到一个查询请求后,会先去查询缓存里找,缓存中有key-value对形式的数据,key是sql语句,value是结果。如果能找到就返回结果,找不到就执行后面阶段(到分析器),执行结果会被存在查询缓存

2.2但是多数情况下并不建议用查询缓存,因为非常容易失效,弊端如下:

一张表只要更新查询缓存就会被清空(这点就足够致命)

②除非是一张静态表,否则查询缓存命中率非常低

2.3mysql(8.0之前的版本)支持手动开启查询缓存

img

3.分析器

①先进行词法分析,对sql语句字符串中每个词进行分析分别表示什么,比如select,就表示是查询语句

②接着进行语法分析根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。

在分析器中,会先进行一次precheck权限验证,验证是否有对这个表进行操作的权限,但是precheck是无法对运行时涉及到的表进行权限验证的,所以下面执行器里还有一次验证

小结:分析器是让mysql知道自己要做什么

4.优化器

优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。比如你执行下面这样的语句,这个语句是执行两个表的 join:

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

img

这里要注意:并不是谁t1写在前面就先查t1,而是要让优化器去选依照怎样的执行顺序效率最高

小结:优化器负责sql语句的执行方案,也就是知道该怎么做

5.执行器

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

查询也会在优化器之前(也就是分析)调用 precheck 验证权限。而precheck是无法对运行时涉及到的表进行权限验证的,比如使用了触发器的情况。因此在执行器这里也要做一次执行时的权限验证。

(疑惑:为什么不能在分析器里一次验证完呢)

②如果有权限就打开表,然后根据表的引擎定义去使用这个引擎提供的接口

(所以到了执行的时候才会进入到数据库引擎,然后执行器也是通过调用数据库引擎的API来进行数据操作的。也因此数据库引擎才会是插件形式的)

③对于开始的那个sql语句,如果没有索引,就会一行一行地进行取数据还有判断,符合条件的放到结果集

对于有索引的表,执行的逻辑也差不多。第一次调用的是“取满足条件的第一行”这个接口,之后循环取“满足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。

你会在数据库的慢查询日志中看到一个 rows_examined 的字段,它的数值和执行器的调用次数有关,一般要少于引擎扫描的行数 (这个比较好理解)

慢查询日志的概念,简单来说就是记录超时的sql(慢日志的具体使用见这条博客笔记:https://blog.csdn.net/qq_39687662/article/details/116854566)

img

执行下面这行代码可以找到慢查询日志的位置

SHOW VARIABLES LIKE '%quer%';

img

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值