【MySQL 读书笔记】当我们在执行该查询语句的时候我们在干什么
看了非常多 MySQL 相关的书籍和文章,没有看到过如此优秀的专栏。所以未来一段时间我会梳理读完该专栏的所学所得。
当我们在执行该查询语句的时候我们在干什么
mysql> select * from T where ID=10;
让我们先来看一个架构示意图

MySQL 架构被清晰的分为了两层,服务器层 | 存储引擎层。
服务器层一般用于存放一些可以跨存储引擎执行的功能,Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),还有存储过程、触发器、视图等。
存储引擎层主要是负责数据的存储和提取,它是一个可插拔的状态。目前我们接触最多的肯定是 Innodb 了,我还使用过 PERCONA 的 Tokudb ,也是一个非常高性能支持事务的存储引擎。
下面和文章一样我们来走一遍执行该查询语句会经历哪些操作。
连接器
首先我们 MySQL 客户端,你可以理解为是我们常用于查询的 ORM 发起的连接到 MySQL 的连接器。连接器如图上标识的用于管理连接和进行权限验证。当我们连接上 MySQL 之后如果没有开始查询,我们的连接将会处于 Sleep 状态。如果我们太长时间没有进行任何查询,连接将会被 MySQL 断开。这个时候如果我们使用 ORM 进行请求就会报错了,需要我们重新连接,进行查询。
当然 MySQL 断开这个时间是通过参数控制的,这个参数是 wait_timeout 默认是 8 个小时
mysql> show variables like '%timeout%';
+-----------------------------+----------+
| Variable_name | Value |
+-----------------------------+----------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| have_statement_timeout | YES |
| innodb_flush_log_at_timeout | 1 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 60 |
| wait_timeout | 28800 |
+-----------------------------+----------+
这里我多提一句,我在对比 MySQL 5.6 和 5.7 参数的时候发现多出来一个参数
have_statement_timeout 默认是 YES, 这个参数用于设置 select 查询语句的超时时间特性开启。
可以通过使用语句
56551 rows in set (0.11 sec) mysql> SELECT /*+ MAX_EXECUTION_TIME(100) */ * FROM ad_day_yxs1812_pay_detail;
ERROR 3024 (HY000): Query execution was interrupted, maximum statement execution time exceeded
来设置一个最大的查询时间,如果查询时间超过这个时间则会报错。可以看到查询这56551 需要 0.11 sec 也就是 110 ms 我设置了 100ms 的查询时间所以没有办法得到结果就被打断了。
查询缓存
建立完连接之后就会走到查询缓存这一步,其实这可能是 MySQL 最没用的特性之一,查询缓存失效非常频繁,只要有数据发生更新,查询缓存就会失效。
我估摸着这个功能之前可能是用于缓存大量静态数据,但是现在都有 redis 之类的 NoSQL 来 handle 此类情况。所以我也想不到什么场景这个开启会比较有用,有个好消息是 MySQL 官方在 8.0 的时候彻底删除了该功能。
分析器
分析器负责把你的语句进行一些词法分析,如果你的语法有错误将会抛出错误进行提示。分析器处理完语句之后,MySQL 就知道该语句要做什么了。MySQL 的分析器部分分为 词法分析和语法规则。这两个将会生成一颗解析树提供给后面我们要讲到的优化器组件使用。
如果说我们执行
select * from T where k=1
然后没有 k 这一列就会被分析器这一层抛出错误。分析器会帮我们判断表和列是否存在。
优化器
优化器将根据上面的的的解析树生成执行计划。同时优化器还负责选择索引的事情,还有多表关联 join 的时候选择哪个表在前哪个表在后。
执行器
当优化器处理之后就到执行的时候了,开始执行的时候会判断我对该表的操作有没有权限,如果没有会返回权限错误。如果有权限就可以请求引擎的接口查询数据。
对于没有能使用索引的表执行:
1. 调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 10,如果不是则跳过,如果是则将这行存在结果集中
2. 调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
3. 执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
对于有索引的表执行:
对于有索引的表,执行的逻辑也差不多。第一次调用的是“取满足条件的第一行”这个接口,之后循环取“满足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。
你会在数据库的慢查询日志中看到一个 rows_examined 的字段,表示这个语句执行过程中扫描了多少行。这个值就是在执行器每次调用引擎获取数据行的时候累加的。
在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的。
Reference:
本读书笔记皆来自发布在极客时间的 林晓斌(丁奇)的 MySQL 实战45讲:
极客时间版权所有: https://time.geekbang.org/ 版权所有:
https://time.geekbang.org/column/article/68319
https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_have_statement_timeout
https://www.jiqizhixin.com/articles/2018-12-12-17 MySQL内核源码解读-SQL解析之解析器浅析
【MySQL 读书笔记】当我们在执行该查询语句的时候我们在干什么的更多相关文章
- EF5中 执行 sql语句使用Database.ExecuteSqlCommand 返回影响的行数 ; EF5执行sql查询语句 Database.SqlQuery 带返回值
一: 执行sql语句,返回受影响的行数 在mysql里面,如果没有影响,那么返回行数为 -1 ,sqlserver 里面 还没有测试过 using (var ctx = new MyDbConte ...
- Oracle执行SQL查询语句的步骤
Oracle执行SQL查询语句的步骤 如果用户在SQL*Plus下输入了如下查询语句:SELECT * FROM dept: 查询语句的处理主要包括三个过程:编译(parse).执行(execute) ...
- SpringBoot-JPA删除不成功,只执行了查询语句
今天使用JPA自定义了一个删除方法deleteByUserIdAndCommentId发现并没有删除掉对应的数据,只执行了查询语句 Hibernate: select good0_.id as id1 ...
- oracle执行sql查询语句出现错误ORA-00942:表或视图不存在
情况是这样,A库的用户名和表空间分别为SH , SH 把业务表SH所有数据从A库,导入到B库, 表空间为SH,用户名为SP 在B库里面执行sql查询语句出现错误ORA-00942:表或视图不存在 语句 ...
- 【MySQL 读书笔记】当我们在执行更新语句的时候我们在做什么
该篇其实重点涉及两个日志的使用和处理. 一个是 server 层的 binlog 一个是服务器层的 redolog. 首先还是根据主线来介绍当我们在执行更新语句的时候我们在做什么 Redo Log M ...
- 【MySQL 读书笔记】SQL 刷脏页可能造成数据库抖动
开始今天读书笔记之前我觉得需要回顾一下当我们在更新一条数据的时候做了什么. 因为 WAL 技术的存在,所以当我们执行一条更新语句的时候是先写日志,后写磁盘的.当我们在内存中写入了 redolog 之后 ...
- 【MySQL 读书笔记】普通索引和唯一索引应该怎么选择
通常我们在做这个选择的时候,考虑得最多的应该是如果我们需要让 Database MySQL 来帮助我们从数据库层面过滤掉对应字段的重复数据我们会选择唯一索引,如果没有前者的需求,一般都会使用普通索引. ...
- 【MySQL 读书笔记】RR(REPEATABLE-READ)事务隔离详解
这篇我觉得有点难度,我会更慢的更详细的分析一些 case . MySQL 的默认事务隔离级别和其他几个主流数据库隔离级别不同,他的事务隔离级别是 RR(REPEATABLE-READ) 其他的主流数据 ...
- 【MySQL 读书笔记】全局锁 | 表锁 | 行锁
全局锁 全局锁是针对数据库实例的直接加锁,MySQL 提供了一个加全局锁的方法, Flush tables with read lock 可以使用锁将整个表的增删改操作都锁上其中包括 ddl 语句,只 ...
随机推荐
- Docker进阶之四:centos7安装docker
centos7.6 安装docker 参考:https://docs.docker.com/install/linux/docker-ce/centos/ 一.存在老版本先删除 yum remove ...
- SLAM+语音机器人DIY系列:(二)ROS入门——7.理解tf的原理
摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...
- JAVA WEB快速入门之通过一个简单的Spring项目了解Spring的核心(AOP、IOC)
接上篇<JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构.调试.部署>,通过一个简单的JSP WEB网站了解了JAVA WEB相关的知识,比如:Ser ...
- 初步认识Swiper_前端交互控制神器_滚动3D切换等特效简单制作
前言: 本人在项目的工作中负责研发,页面及交互基本都是交给前端去做的.以前前端写的东西大概都知道,都是一些JS,CSS和HTML等的一些基本控制,都懂!但是今天前端突然做了一个具有特殊效果的DOM:页 ...
- C# 提前异步加载数据
前言 在我们应用程序中,如果有较大的数据需要从数据库或者本地读取,且是一次性的话,可以提前获取数据并缓存在内存中. 一般处理方法:利用应用程序启动到用户使用功能这一段时间,提前加载数据. 问题来了,因 ...
- Java集合类源码解析:Vector
[学习笔记]转载 Java集合类源码解析:Vector 引言 之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector.为什么说是它兄弟呢?因为从容器的构造来说,Vec ...
- 折腾Java设计模式之迭代器模式
迭代器模式 Provide a way to access the elements of an aggregate object sequentially without exposing its ...
- (四) Keras Dropout和正则化的使用
视频学习来源 https://www.bilibili.com/video/av40787141?from=search&seid=17003307842787199553 笔记 使用drop ...
- SQL运维
1.碎片扫描 dbcc showconfig('table_name')
- MongoDB自学(3)
MongoDB关系:MongoDB的关系表示多个文档之间在逻辑上的相互联系.文档之间可以通过嵌入和引用来建立联系.关系:1:11:NM:1M:N 嵌入式:{ id:11;name:嘻嘻嘻;addres ...