思维导航:

  • 写操作执行过程

  • 组件介绍

    • 1、undo log 与 MVCC

    • 2、redo log 与 Buffer Pool

    • 3、bin log(Server 层)

    • 1、连接器

    • 2、缓存(Cache)

    • 3、分析器

    • 4、优化器

    • 5、执行器

    • Server层

    • 存储引擎(InnoDB)层

    • 三个日志的比较(undo、redo、bin)

  • 执行过程

    • Where 条件的提取

    • 写操作

    • 读操作

文章正文:

?回到顶部

写操作执行过程

  如果这条sql是写操作(insert、update、delete),那么大致的过程如下,其中引擎层是属于 InnoDB 存储引擎的,因为InnoDB 是默认的存储引擎,也是主流的,所以这里只说明 InnoDB 的引擎层过程。由于写操作较查询操作更为复杂,所以先看一下写操作的执行图。方便后面解析。

?回到顶部

组件介绍

Server层

1、连接器

  1)负责与客户端的通信,是半双工模式,这就意味着某一固定时刻只能由客户端向服务器请求或者服务器向客户端发送数据,而不能同时进行。

  2)验证用户名和密码是否正确(数据库mysql的user表中进行验证),如果错误返回错误通知(deAcess  nied  for  user  'root'@'localhost'(using password:YES)),如果正确,则会去 mysql 的权限表(mysql中的 user、db、columns_priv、Host 表,分别存储的是全局级别、数据库级别、表级别、列级别、配合 db 的数据库级别)查询当前用户的权限。

2、缓存(Cache)

  也称为查询缓存,存储的数据是以键值对的形式进行存储,如果开启了缓存,那么在一条查询sql语句进来时会先判断缓存中是否包含当前的sql语句键值对,如果存在直接将其对应的结果返回,如果不存在再执行后面一系列操作。如果没有开启则直接跳过。

相关操作

查看缓存配置:show  variables  like  'have_query_cache';

查看是否开启:show  variables  like  'query_cache_type';

查看缓存占用大小:show  variables  like  'query_cache_size';

查看缓存状态信息:show  status  like  'Qcache%';

相关参数的含义:

 缓存失效场景

1、查询语句不一致。前后两条查询SQL必须完全一致。

2、查询语句中含有一些不确定的值时,则不会缓存。比如 now()、current_date()、curdate()、curtime()、rand()、uuid()等。

3、不使用任何表查询。如 select 'A';

4、查询 mysql、information_schema 或 performance_schema 数据库中的表时,不会走查询缓存。

5、在存储的函数,触发器或事件的主体内执行的查询。

6、如果表更改,则使用该表的所有高速缓存查询都变为无效并从缓存中删除,这包括使用 MERGE 映射到已更改表的表的查询。一个表可以被许多类型的语句改变,如 insert、update、delete、truncate rable、alter table、drop table、drop database。

通过上面的失效场景可以看出缓存是很容易失效的,所以如果不是查询次数远大于修改次数的话,使用缓存不仅不能提升查询效率还会拉低效率(每次读取后需要向缓存中保存一份,而缓存又容易被清除)。所以在 MYSQL5.6默认是关闭缓存的,并且在 8.0 直接被移除了。当然,如果场景需要用到,还是可以使用的。

开启

在配置文件(linux下是安装目录的cnf文件,windows是安装目录下的ini文件)中,增加配置: query_cache_type = 1

关于 query_type_type 参数的说明:

指定 SQL_NO_CACHE:select  SQL_NO_CACHE  *  from  student  where age >20;    SQL_CACHE 同理。

3、分析器

对客户端传来的 sql 进行分析,这将包括预处理与解析过程,并进行关键词的提取、解析,并组成一个解析树。具体的解析词包括但不局限于 select/update/delete/or/in/where/group by/having/count/limit 等,如果分析到语法错误,会直接抛给客户端异常:ERROR:You have an error in your SQL syntax.

比如:select *  from user where userId =1234;

在分析器中就通过语义规则器将select from where这些关键词提取和匹配出来,mysql会自动判断关键词和非关键词,将用户的匹配字段和自定义语句识别出来。这个阶段也会做一些校验:比如校验当前数据库是否存在user表,同时假如User表中不存在userId这个字段同样会报错:unknown column in field list.

4、优化器

进入优化器说明sql语句是符合标准语义规则并且可以执行。优化器会根据执行计划选择最优的选择,匹配合适的索引,选择最佳的方案。比如一个典型的例子是这样的:

表T,对A、B、C列建立联合索引(A,B,C),在进行查询的时候,当sql查询条件是:select xx where  B=x and A=x and C=x.很多人会以为是用不到索引的,但其实会用到,虽然索引必须符合最左原则才能使用,但是本质上,优化器会自动将这条sql优化为:where A=x and B=x and C=X,这种优化会为了底层能够匹配到索引,同时在这个阶段是自动按照执行计划进行预处理,mysql会计算各个执行方法的最佳时间,最终确定一条执行的sql交给最后的执行器

5、执行器

执行器会调用对应的存储引擎执行 sql。主流的是MyISAM 和 Innodb。

存储引擎(InnoDB)层

1、undo log 与 MVCC

undo log是 Innodb 引擎专属的日志,是记录每行数据事务执行前的数据。主要作用是用于实现MVCC版本控制,保证事务隔离级别的读已提交和读未提交级别。而 MVCC 相关的可以参考 MySQL中的事务原理和锁机制。

2、redo log 与 Buffer Pool

InnoDB 内部维护了一个缓冲池,用于减少对磁盘数据的直接IO操作,并配合 redo log 来实现异步的落盘,保证程序的高效执行。redo log 大小固定,采用循环写

write pos 表示当前正在记录的位置,会向后记录, checkpoint 表示数据落盘的边界,也就是 checkpoint 与 write pos中间是已记录的,当 write pos写完 id_logfile_3后,会回到id_logfile_0循环写,而追上 checkpomnit 后则需要先等数据进行落盘,等待 checkponit向后面移动一段距离再写。redo log存储的内容个人认为当直接更新到数据页缓存时记录的就是数据页逻辑,如果更新到 Change Buffer 那么就是操作的 sql。

关于 Buffer Pool详情可查看博客 InnoDB 中的缓冲池(Buffer Pool)。

3、bin log(Server 层)

redo log 因为大小固定,所以不能存储过多的数据,它只能用于未更新的数据落盘,而数据操作的备份恢复、以及主从复制是靠 bin log(如果数据库误删需要还原,那么需要某个时间点的数据备份以及bin log)。5.7默认记录的是修改后的行记录。

在更新到数据页缓存或者 Change Buffer 后,首先进行 redo log 的编写,此时 redo log 处于 prepare 状态,随后再进行 bin log 的编写,等到 bin log 也编写完成后再将 redo log 设置为 commit 状态。这是为了防止数据库宕机导致 bin log 没有将修改记录写入,后面数据恢复、主从复制时数据不一致。当数据库启动后如果发现 redo log 为 prepare 状态,那么就会检查 bin log 与 redo log 最近的记录是否对的上,如果对的上就提交,对不上就进行事务回滚。

三种格式:

1、Row(5.7默认)。记录被修改后的行记录。缺点是占空间大。优点是能保证数据安全,不会发生遗漏。

2、Statement。记录修改的 sql。缺点是在 mysql 集群时可能会导致操作不一致从而使得数据不一致(比如在操作中加入了Now()函数,主从数据库操作的时间不同结果也不同)。优点是占空间小,执行快。

3、Mixed。会针对于操作的 sql 选择使用Row 还是 Statement。缺点是还是可能发生主从不一致的情况。

三个日志的比较(undo、redo、bin)

1、undo log是用于事务的回滚、保证事务隔离级别读已提交、可重复读实现的。redo log是用于对暂不更新到磁盘上的操作进行记录,使得其可以延迟落盘,保证程序的效率。bin log是对数据操作进行备份恢复(并不能依靠 bin log 直接完成数据恢复)。

2、undo log 与 redo log 是存储引擎层的日志,只能在 InnoDB 下使用;而bin log 是 Server 层的日志,可以在任何引擎下使用。

3、redo log 大小有限,超过后会循环写;另外两个大小不会。

4、undo log 记录的是行记录变化前的数据;redo log 记录的是 sql 或者是数据页修改逻辑或 sql(个人理解);bin log记录的是修改后的行记录(5.7默认)或者sql语句。

?回到顶部

执行过程

写操作

通过上面的分析,可以很容易地了解开始的更新执行图。这里就不过多阐述了。

读操作

查询的过程和更新比较相似,但是有些不同,主要是来源于他们在查找筛选时的不同,更新因为在查找后会进行更新操作,所以查询这一行为至始至终都在缓冲池中(使用到索引且缓冲池中包含数据对应的数据页)。而查询则更复杂一些。

Where 条件的提取

在 MySQL 5.6开始,引入了一种索引优化策略——索引下推,其本质优化的就是 Where 条件的提取。Where 提取过程是怎样的?用一个例子来说明,首先进行建表,插入记录。

create table tbl_test (a int primary key, b int, c int, d int, e varchar(50));create index idx_bcd on tbl_test(b, c, d);insert into tbl_test values (4,3,1,1,'a');insert into tbl_test values (1,1,1,2,'d');insert into tbl_test values (8,8,7,8,'h');insert into tbl_test values (2,2,1,2,'g');insert into tbl_test values (5,2,2,5,'e');insert into tbl_test values (3,3,2,1,'c');insert into tbl_test values (7,4,0,5,'b');insert into tbl_test values (6,5,2,4,'f');

那么执行 select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != 'a';  在提取时,会将 Where 条件拆分为 Index Key(First Key & Last Key)、Index Filter 与 Table Filter

1、Index Key

用于确定 SQL 查询在索引中的连续范围(起始点 + 终止点)的查询条件,被称之为Index Key;由于一个范围,至少包含一个起始条件与一个终止条件,因此 Index Key 也被拆分为 Index First Key 和 Index Last Key,分别用于定位索引查找的起始点以终止点

    Index First Key

    用于确定索引查询范围的起始点;提取规则:从索引的第一个键值开始,检查其在 where 条件中是否存在,若存在并且条件是 =、>=,则将对应的条件加入Index First Key之中,继续读取索引的下一个键值,使用同样的提取规则;若存在并且条件是 >,则将对应的条件加入 Index First Key 中,同时终止 Index First Key 的提取;若不存在,同样终止 Index First Key 的提取

    针对 SQL:select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != 'a',应用这个提取规则,提取出来的 Index First Key 为 b >= 2, c > 0 ,由于 c 的条件为 >,提取结束

    Index Last Key

    用于确定索引查询范围的终止点,与 Index First Key 正好相反;提取规则:从索引的第一个键值开始,检查其在 where 条件中是否存在,若存在并且条件是 =、<=,则将对应条件加入到 Index Last Key 中,继续提取索引的下一个键值,使用同样的提取规则;若存在并且条件是 < ,则将条件加入到 Index Last Key 中,同时终止提取;若不存在,同样终止Index Last Key的提取

    针对 SQL:select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != 'a',应用这个提取规则,提取出来的 Index Last Key为 b < 7 ,由于是 < 符号,提取结束

2、Index Filter

在完成 Index Key 的提取之后,我们根据 where 条件固定了索引的查询范围,那么是不是在范围内的每一个索引项都满足 WHERE 条件了 ?很明显 4,0,5 , 2,1,2 均属于范围中,但是又均不满足SQL 的查询条件

    所以 Index Filter 用于索引范围确定后,确定 SQL 中还有哪些条件可以使用索引来过滤;提取规则:从索引列的第一列开始,检查其在 where 条件中是否存在,若存在并且 where 条件仅为 =,则跳过第一列继续检查索引下一列,下一索引列采取与索引第一列同样的提取规则;若 where 条件为 >=、>、=、>、

    针对 SQL:select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != 'a',应用这个提取规则,提取出来的 Index Filter 为 c > 0 and d != 2 ,因为索引第一列只包含 >=、< 两个条件,因此第一列跳过,将余下的 c、d 两列加入到 Index Filter 中,提取结束

3、Table Filter

这个就比较简单了,where 中不能被索引过滤的条件都归为此中;提取规则:所有不属于索引列的查询条件,均归为 Table Filter 之中

针对 SQL:select * from tbl_test where b >= 2 and b < 7 and c > 0 and d != 2 and e != 'a',应用这个提取规则,那么 Table Filter 就为  e != 'a'

在5.6 之前,是不分 Table Filter 与 Index Filter 的,这两个条件都直接分配到 Server 层进行筛选。筛选过程是先根据 Index Key 的条件先在引擎层进行初步筛选,然后得到对应的主键值进行回表查询得到初筛的行记录,传入 Server 层进行后续的筛选,在 Server 层的筛选因为没有用到索引所以会进行全表扫描。而索引下推的优化就是将 Index Filter 的条件下推到引擎层,在使用  Index First Key 与 Index Last Key 进行筛选时,就带上 Index Filter 的条件再次筛选,以此来过滤掉不符合条件的记录对应的主键值,减少回表的次数,同时发给 Server 层的记录也会更少,全表扫描筛选的效率也会变高。下面是未使用索引下推和使用索引下推的示意图。

从上面的分析来看,查询的流程图大致可以用下面这张图来概括

这里要注意的是如果在一开始没有用到索引,会依次将磁盘上的数据页读取到缓冲池中进行查询。

出处:https://www.cnblogs.com/mengxinJ/p/14045520.html

版权申明:本文来源于网友收集或网友提供,如果有侵权,请转告版主或者留言,本公众号立即删除。

sql server修改字段编码格式_原理:一条 sql 的执行过程详解相关推荐

  1. sql server修改字段编码格式_关于MySQL如何修改character_set_client的编码问题

    问题引入: 我们经常会遇到一些向MySQL数据库中插入中文,但是select出来的时候,却发现是乱码的情况.如我们向表a出入这样一段记录:i insert into a values('你好hello ...

  2. sql server 2005管理员手册_执行一条sql语句都经历了什么?

    每天都在跟 mysql 打交道,你知道执行一条简单的 select 语句,都经历了哪些过程吗? 首先,mysql 主要是由 server 层和存储层两部分构成的.server 层主要包括连接器.查询缓 ...

  3. sql server(MsSql)字段命名,表命名,视图命名,SQL语句书写参考

    @[TOC](sql server(MsSql)字段命名,表命名,视图命名,SQL语句书写参考) 对我个人来说,字段命名,表命名,视图命名,SQL语句书写都有一套自己的习惯,可以减少维护成本.减少不必 ...

  4. SQL Server时间粒度系列----第4节季、年时间粒度详解

    本文目录列表: 1.SQL Server季时间粒度 2.SQL Server年时间粒度 3.总结语 4.参考清单列表 SQL Serve季时间粒度   季时间粒度也即是季度时间粒度.一年每3个月是一个 ...

  5. sql 获取数据库字段信息_使用DBATools获取SQL数据库详细信息

    sql 获取数据库字段信息 In the series of articles on DBATools, (see TOC at the bottom) we are exploring useful ...

  6. linux efi 启动原理,Linux(RHEL6)启动过程详解

    Linux(RHEL6)启动过程详解 Linux(红帽RHEL6)启动过程详解: RHEL的一个重要和强大的方面是它是开源的,并且系统的启动过程是用户可配置的.用户可以自由的配置启动过程的许多方面,包 ...

  7. sql server修改索引名称_【索引潜规则】覆盖索引、ICP、MRR详解

    点击上方蓝色字体,关注我们 上篇文章我们说了创建索引的方法,有聚簇索引.辅助索引.前缀索引.联合索引等,也说了如何利用索引的排序功能,接着本篇文章主要来说一说索引的几种优化策略,首先我们先说下回表的概 ...

  8. sql server 修改字段长度 及 删除默认值

    1.修改字段长度 alter table tbl_project(表名) alter column  short_description(字段名) varchar(1000); 2.EXECUTE [ ...

  9. SQL Server修改字段修改描述语句

    --创建表   create table 表(a1 varchar(10),a2 char(2)) --修改字段名称 execute sp_rename '表名.字段名','新字段名' execute ...

最新文章

  1. Android中怎么使图片显示
  2. acwing算法题--看图做题
  3. android 5.0新增 ui 控件,android3.0新增ui控件示例说明.doc
  4. javascript使用_用JavaScript唤醒沉睡的城市
  5. 深入浅出 SpringMVC - 1
  6. 一文带你实现RPC框架
  7. C#AutoResetEvent和ManualResetEvent的区别
  8. mikumikudance
  9. maven的全局setting及用户setting
  10. NuttX 任务管理
  11. NetFPGA-1G-CML从零开始环境配置
  12. gridview纯图片九宫图展示
  13. CLIP论文笔记--《Learning Transferable Visual Models From Natural Language Supervision》
  14. python连接Google文档操作步骤总结
  15. 深度学习基础--分类网络
  16. JSP众筹管理系统myeclipse开发sql数据库web结构计算机java编程
  17. 网页设计中的安全字体
  18. 微信支付宝手机网站支付(WAP)
  19. zzulioj 1804: ZY学长的密码 (字符串)
  20. 数据挖掘(六):预测

热门文章

  1. 关于赠书《VS Code》断货延迟的通知!
  2. 赠书:一本书揭开 Spring Boot 技术内幕
  3. 一口气带你踩完五个 List 的大坑!
  4. 未来计算机将怎么样改变我的生活,未来人类都不用上班 人工智能将如何改变我们的生活?...
  5. Deepsort_V2 2020中兴捧月阿尔法赛道多目标检测和跟踪初赛第一名
  6. python获取硬件信息
  7. 南阳理工大学 gnns 新基准
  8. graphviz.backend.ExecutableNotFound: failed to execute ['dot', '-Tpdf', '-O', 'Digraph.gv']
  9. with error 126:找不到指定的模块
  10. python计算相关系数