首页 > 数据库 >1.MySql基础架构之SQL语句的执行

1.MySql基础架构之SQL语句的执行

时间:2025-01-19 16:32:05浏览次数:1  
标签:执行器 语句 缓存 记录 SQL 查询 基础架构 MySql 连接

1.MySQL数据库的整体架构

image-20250119102426368

(i)连接器:连接器负责与客户端建立连接,获取权限、维持和管理连接。连接命令中的mysql是客户端工具,用来建立服务端连接。在完成经典的TCP握手后,连接器就要开始认证你的身份,这个时候用的就是你输入的用户名和密码。

​ 如果用户名密码认证通过,连接器会到权限表里面查出你拥有的权限。之后,这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。

​ 连接完成后,如果你没有后续的动作,这个连接就处于空闲状态,你可以在 showprocesslist 命令中看到它。文本中这个图是 show processlist 的结果,其中的Command 列显示为“Sleep”的这一行,就表示现在系统里面有一个空闲连接。客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数 wait_timeout控制的,默认值是 8 小时。

MySql连接数量的限制

MySQL服务支持的最大连接时由max_connection参数控制的,超过这个数值系统就会拒绝接下来的所有请求,并报错"Too many connections"

MySql长短连接问题

MySQL也和Http一样,有短连接和长连接

短连接概念:

连接mysql服务(TCP三次握手)

执行sql

断开mysql服务(TCP四次挥手 )

长连接概念:

连接mysql服务(TCP三次握手)

执行sql

执行sql

执行sql

...

断开mysql服务(TCP四次挥手)

长连接占用内存过多的问题怎么解决

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

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

连接器内容总结

  • 与客户端进行TCP三次握手连接
  • 校验客户端用户名和密码,如果用户名和密码不对,就会报错
  • 如果用户名和密码都对了,会读取该用户的权限,然后后面的逻辑判断都会基于此权限

2.查询缓存

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

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

但是大部分时候,不建议使用缓存。大多时候查询缓存弊大于利

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

需要注意的是,MySQL 8.0 版本直接将查询缓存的整块功能删掉了,也就是说 8.0 开始彻底没有这个功能了。

3.解析器

(i)词法分析,MySQL会根据你输入的字符串识别出关键字出来

(ii)语法分析,会根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个SQL语句是否满足MySQL语法,如果没有问题就会构建SQL语法树,这样方便后面的模块获取SQL类型、表名,字段名,where条件

4.执行SQL

经过解析器后,就要进行执行SQL查询语句的流程了,每条SELECT查询语句可以分为以下三个阶段

  • prepare阶段,也就是预处理阶段
  • optimize阶段,也就是优化阶段
  • execute阶段,也就是执行阶段

①预处理阶段

  • 检查SQL查询语句中的表或者字段是否存在
  • select *中的*,扩展到所有列

②优化器阶段

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

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

既可以先从表 t1 里面取出 c=10 的记录的 ID 值,再根据 ID 值关联到表 t2,再判断 t2里面 d 的值是否等于 20。

也可以先从表 t2 里面取出 d=20 的记录的 ID 值,再根据 ID 值关联到 t1,再判断 t1 里面 c 的值是否等于 10。

这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。

③执行器阶段

经历完优化器后,就确定了执行方案,接下来MySQL就真的开始执行语句,这个工作是由执行器完成的。在执行的过程中,执行器就会和存储引擎交互了,交互是以记录为单位的。还会判断一下用户是否对该表有操作权限

执行器和存储引擎交互有三种执行过程

  • 主键索引查询
  • 全表扫描
  • 索引下推

主键索引查询

以本文开头查询语句为例,看看执行器是怎么工作的

select * from product where id=1

这条记录语句的查询条件用到了主键索引,而且是等值查询,同时主键id唯一,不会有id不唯一的记录,索引优化器决定用访问类型const进行查询,也就是使用主键索引查询一条记录,那么执行器与存储引擎的执行流程是这样的:

  • 执行器第一次查询,会调用read_first_record函数指针指向的函数,因为优化器选择的访问类型为const,这个函数被指向InnoDB引擎索引查询的接口,把条件id=1交给存储引擎,让存储引擎定位一条符合条件的第一条记录
  • 存储引擎通过主键索引的B+数结构定位到id=1的第一条记录,如果记录不存在的,就会向执行器上报记录找不到错误,然后查询结束。如果记录是存在的,就会将记录返回给执行器
  • 执行器从存储引擎读到记录之后,接着判断记录是否符合查询条件,如果符合则发送给客户端,如果不符合则跳过该记录
  • 执行器查询的过程是一个while循环,所以还会再查一次,但是由于不是第一次查询所以会调用read_record函数指针指向函数,因为优化器选择的访问类型为const,这个函数指针被指向了一个永远返回-1的函数,所以当调用该函数的时候,执行器就退出循环,也就结束查询了。

全表扫描

eg:select * from product where name='phone'

这条查询语句的查询条件没有用到索引,所以优化器决定选用访问类型为ALL进行查询,也就是全表扫描这种方式查询,那么这时执行器与存储引擎的执行流程是这样的:

  • 执行器第一次查询,会调用read_first_record函数指针指向的函数,因为优化器选择的访问类型为ALL,这个函数指针被指向InnoDB引擎全扫描接口,让存储引擎读取表中的第一条记录;
  • 执行器会判断读到的这条记录的name是不是iphone,如果不是则跳过;如果是则将记录发给客户(Server层每从存储引擎读到一条记录就会发送给客户端,之所以客户端显示的是所有记录,是因为客户端在查询完成之后才会显示)
  • 执行器查询的过程是一个while循环,所以还会再查一次,会调用read_record函数指针指向的函数,因为优化器选择的访问类型为all,read_record函数指针指向的还是InnoDB引擎扫描的接口,所以接着向存储引擎层要求继续读刚刚读到的那条记录的下一条记录,存储记录把下一条记录取出后就将其返回给执行器(Server层),执行器继续判断条件,不符合查询条件的即跳过该记录,否则发送到客户端
  • 一直重复上述过程,直到存储引擎把表中的记录全部读完,然后向执行器(Server层)返回了读取完毕的信息
  • 执行器收到存储引擎报告的查询完毕的信息,退出循环,停止查询

索引下推

索引下推能够减少二级索引在查询时的回表操作,提高查询效率,因为它将Server层负责的事情交给了存储引擎去处理了

标签:执行器,语句,缓存,记录,SQL,查询,基础架构,MySql,连接
From: https://www.cnblogs.com/qiwenforever/p/18679676

相关文章

  • MySQL数据库笔记——主从复制
    大家好,这里是GoodNote,关注公主号:Goodnote,本文详细介绍MySQL的主从复制,从原理到配置再到同步过程。文章目录简介核心组件主从复制的原理作用主从复制的线程模型主从复制的模式形式复制的方式设计复制机制主从复制的配置步骤优化和改进总结历史文章简介MySQ......
  • MySQL 创建数据库问题:You have an error in your SQL syntax(MySQL 数据库命名规则问题
    问题描述与处理策略1、问题描述CREATEDATABASEmy-shop-db;执行上述SQL语句,报如下错误CREATEDATABASEmy-shop-db>1064-YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMySQLserverversionfortherightsyntaxtouse......
  • ingress-nginx代理tcp使其能外部访问mysql
    一、helm部署mysql主从复制helmrepoaddbitnamihttps://charts.bitnami.com/bitnamihelmrepoupdate helmpullbitnami/mysql 解压后编辑values.yaml文件,修改如下(storageclass已设置默认类)117##@paramarchitectureMySQLarchitecture(`standalone`or`re......
  • MySQL数据库基本操作命令
    数据库基本操作数据库可以看作是一个专门存储数据对象的容器,每一个数据库都有唯一的名称,并且数据库名称都是有实际意义的,这样就可以清晰的看出每一个数据库用来存放什么数据。在MySQL数据库中存在系统数据库和自定义数据库,系统数据库是安装在MySQL后系统自带的数据库,自定义......
  • MySQL——DQL基本查询 聚合函数 分组查询 排序查询 分页查询
    1.3DQL语法DQL:数据查询语言,用来查询数据库表中的记录。DQL基本查询1.查询多个字段select字段1,字段2,字段3...from表名;案例查询指定字段nameworknoageselectname,workno,agefromemp;2.查询所有字段select*from表名;select*fromemp;3.设置别名select字段1a......
  • N个utils(sql)
    sql,操作数据库的语言,也可以叫做数据库软件的指令集吧。名字而已,无所谓啦。本质上,sql并不是java语言内的范畴。但却是企业级开发的范畴。并且我整个文章的一篇逻辑的本质,层的概念,其中一个大的层级就是指,数据库。在数据库下,还能有库  表   数据行   字段最基本的......
  • Golang结合MySQL和DuckDB提高查询性能
    要在Golang中组合MySQL和DuckDB以提高查询性能,请考虑使用混合查询执行方法。这种方法利用了MySQL强大的事务管理和DuckDB闪电般的分析处理能力。本文介绍如何充分利用两者的方法。各取所长用MySQL处理事务,用DuckDB处理分析MySQL应该处理常规的INSERT、UPDATE和DELETE操......
  • 免费送源码:Java+ssm+MySQL SSM宁夏地区自助旅游管理系统 计算机毕业设计原创定制
     摘 要本论文主要论述了如何使用SSM框架开发一个自助旅游管理系统,严格按照软件开发流程进行各个阶段的工作,采用B/S架构JAVA技术,面向对象编程思想进行项目开发。在引言中,作者将论述自助旅游管理系统的当前背景以及系统开发的目的,后续章节将严格按照软件开发流程,对系统进行各......
  • 宿舍管理信息系统【控制台+MySQL】(Java课设)
      客官进来看一眼呗,有惊喜!【帮你解决烦恼】:Java课设和计Java毕设太难不会做怎么办?系统类型控制台类型+Mysql数据库存储数据使用范围适合作为Java课设!!!部署环境jdk1.8+Mysql8.0+Idea或eclipse+jdbc运行效果本系统源码地址:宿舍管理信息系统【控制台+MySQL】(Java课设)资......
  • libsql bottomless 集成minio 简单使用
    libsql支持bottomless可以方便的将wal数据存储在s3中(基于了虚拟wal接口实现),以下是一个简单使用环境准备docker-compose环境开启了namespace以及集成主从服务services:db1:image:ghcr.io/tursodatabase/libsql-server:latestentrypoint:/bin/sqld--db-p......