当前位置:   article > 正文

一条sql语句的执行过程(查询、更新)_更新和查询一条sql实现

更新和查询一条sql实现


思考:一条mysql的执行语句,经过了哪些流程
​​
​​
在这里插入图片描述

1、连接层
mysql服务端,暴露了一个3306端口,客户端用什么协议和他连接?
mysql支持多种协议,一般我们都是使用TCP (mysql-connector-java-x.x.xx.jar)

  mysql-connector-java-x.x.xx.jar: 看了下代码,是解析url的 ip  port  协议,建立了socket连接
  • 1

在这里插入图片描述

              连接方式:可以支持同步和异步

                        同步通信一般依赖于被调用方,会被阻塞,等待被调用方返回结果

                        异步和同步相反,异步可以减少阻塞的时间,但是并不能减少sql执行的时间。存在一个问题,并发情                           况下,异步会创建大量的连接。可以使用线程池。但是对于异步结果的返回还是不可控。一般我们使用同步的方式

               长连接还是短连接:都支持,但是在连接池中一般使用长连接。

                         show global variables like 'wait_timeout'; -- 非交互式超时时间,如 JDBC 程序  默认8小时
                         show global variables like 'interactive_timeout'; -- 交互式超时时间,如数据库工具 默认8小时

                         show variables like 'max_connections'; 最大连接数  默认151
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

通信方式:单工 半双工(mysql是半双工,客户端和服务端可以交互,但是不能同时发送) 全双工

其他:除了建立连接外,还有验证鉴权等功能

2、缓存
mysql 5.x 支持缓存的。结构是key-value,key是查询语句,value是查询结果。当key命中时,可以直接返回,不调用后续分析优化执行过程。但是当表中数据有任意修改时,缓存就失效了意义不大,缓存默认是关闭的,8.x废弃缓存,可以交给缓存框架或者ORM框架处理,这部分可以看mybatis的缓存模块涉及。

3、解析器(分析器)
我们输入一条sql,通信问题ok了,缓存不管,后面应该怎么处理呢?是解析。

在这里插入图片描述

    mysql对于词法的判断,其实是会将一个完整的sql,打散成一个个单词,从哪开始,到哪结束

    语法解析,将所有的词,组装到一个解析树内,实现解析校验
  • 1
  • 2
  • 3

在这里插入图片描述

sql语句解析完成了,又如何知道我们的表和字段不存在的呢?

在这里插入图片描述

 对于表和字段等操作,mysql提供了解析器,来实现检查表名列名,别名等语法没办法解析的数据,封装成一个新的解析树。
  • 1

4、优化器
对于一个sql,mysql其实是有很多种执行方法的,但是具体最后选择了哪一种执行方法,还是由查询优化器来决定的。

执行优化器也还是有自己的判断标准的,mysql中使用的是cost(基于开销的优化器),哪个开销小,选哪个。

优化器可以做哪些,简单举个例子:

1、两张表关联查询,以哪张表为基表

    select * from a left join b on a.id = 10 and b.id = 20

    查询方案有两种:
            先查询a表 id= 10 的数据,再一个一个关联b,判断b.id=20

            先查询b表 id=20  ............... 关联a,判断a.id=10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2、同时可以使用多个索引,使用哪个索引。

备注:优化器其实也是代码,还是得优先提高sql的质量。

优化器优化后,还是将解析树变化成一个查询执行计划。

查询计划的工具: EXPLAIN select name from user where id=1;

备注: EXPLAIN 也不一定是最终执行的方式

5、执行器
优化器提供了具体的执行计划,调用存储引擎api,查询数据

未命中索引:一行一行拿数据,匹配所有

命中索引:类似,调用api拿命中索引的第一行数据,再next next

6、存储引擎
插件的形式,实现规范即可,innodb myisam memory等,默认innodb

mysql每个表都可以指定不同的存储引擎,并且可以修改 show table status where name = ‘user_innodb’;

查看数据的存储位置。就在如下目录中:

在这里插入图片描述

innodb有frm和ibd两个文件 frm存储表结构信息 ibd存储索引和数据信息(聚集索引和非聚集索引)

myisam 有frm MYD MYI三个文件 frm:存储表结构信息 MYD: myisam data MYI: myisam index

在这里插入图片描述

对比一下Innodb和myisam:

myisam是5.5之前的默认的存储引擎 innodb是5.5之后的

innodb默认支持事物(undo.log redo.log 这个后续再介绍),支持行级别的锁,写不阻塞读MVCC 一般数据一致性要求高,使用

myisam只支持表级别锁 (限制了读写的能力,一般也只是用读多写少的场景), insert和select的速度更快

  • 大文件导入时,是不是可以先设置为myisam 然后再转换成innodb,黑操作!

上面的例子是查询语句,可以再看下更新语句

大致逻辑和查询其实是一致的

连接器-》分析器-》优化器-》执行器-》存储引擎

执行器执行器后面的逻辑如下:

1、根据优化器的执行计划去innodb获取数据,

2、存储引擎 先找内存,内存没有就读磁盘加载到内存,返回给执行器

3、执行器修改新的值到行,并调用存储引擎。

4、innodb 先记redo log (物理数据:真实的数据)并设置状态为prepare,返回成功给执行器

5、执行器记bin log (逻辑数据:记录具体的操作 +1 、 -1这种)

6、调用innodb 设置redo log为 commit

7、执行器返回成功

下面的几张图来自《mysql 45讲》

在这里插入图片描述

上述提到了两个重要的文件redo log和bin log,mysql中有很多利用log的设计。

redo log:

在这里插入图片描述

redo log innodb特有的

目的:磁盘写太慢了,利用日志顺序读写快很多。提高效率

在这里插入图片描述

为什么 redo log需要两阶段提交?

站在随时随地都有可能崩溃的情况来看,写bin log 和写 redo log是两个动作,当redo log写完,

崩溃了,恢复后会有该记录对应的数据。这时bin log中没有,那么备份的数据就不一致了

redo log和bin log的区别?
1、redo log是innodb特有,引擎层。bin log是server层的。
2、redo log是循环写入,满了会覆盖。bin log是追加写
3、redo log记录的是物理日志,作用于崩溃恢复处理。而bin log记录的是逻辑日志,用于备份的复制等场景(回放sql记录)。

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/168708
推荐阅读
相关标签
  

闽ICP备14008679号