结构介绍:查询语句是如何执行的

结构介绍:查询语句是如何执行的

在这里插入图片描述

总体来说,mysql分为了Server层与存储引擎层

  1. Server层:连接器、查询缓存、分析器、优化器、执行器。
    跨存储引擎的功能、mysql的核心服务功能、所有的内置函数,都在这一层完成。
    例如:存储过程、视图、数学函数、加密函数
  2. 存储引擎层:负责数据的存储和提取。
    插件式
    常见:
    • Innodb: mysql5.5.5之后的默认存储引擎,支持事务、行锁、外键,适用于读写场景
    • MyISAM: 不支持事务、行锁、外键,保存具体的数据量,所以select count(*) from table执行速度非常快。适用于读场景
    • Memory:创建内存临时表时的默认存储引擎

一条查询sql的执行流程:

  1. 建立连接

    mysql -h$ip -P$port -u$user -p
    

    上述命令中的"mysql"指mysql数据库的客户端连接工具,此命令输入完成后将与服务器建立TCP连接
    几点注意:

    1. 不建议直接在-p参数后缀密码,因为这样导致密码明文直接暴露在数据报文中,不安全。

    2. 如果密码错误,会报“Access denied for user”的错误

    3. 连接成功后,连接器会自动进入权限表(mysql自带的四个数据库之一的mysql数据库下的表都是权限表)读取此连接用户的权限

    4. 第3条意味着,一旦用户连接到mysql服务器,管理员之后对权限进行的修改操作不能影响已连接的用户

    5. 如果客户端一段时间没有进行操作,则mysql会自动断开服务,这个时间由wait_timeout变量设置。
      查看mysql全局变量的命令是

      show global variables like 'wait_timeout'
      

      设置mysql全局变量的命令是

      set global wait_timeout=28800;  
      

      在这里插入图片描述

    6. 连接完成后,可以通过命令来查看已建立的mysql连接

      show processlist
      

在这里插入图片描述
问题:

  1. 我们已经知道了客户端连接mysql服务器实际是建立了TCP连接,TCP连接的建立是比较耗费资源的。所以我们在项目中通常使用连接池来进行连接的复用,如果全部使用长连接,并且长时间不清理连接的话,就会造成mysql内存飞涨,使得连接被MySQL强行kill掉,造成连接异常中断。
    解决方案:①定期断开长连接,或者每当进行复杂查询之后手动断开长连接,在下次需要查询时重新连接。②MySQL5.7以上支持mysql_reset_connection函数用来初始化连接(注意,这个函数是C的api,不是命令行命令)
  2. 查询缓存
    第一步查询的结果会以key-value键值对的形式存放在缓存中,key是查询的语句,value是查询的结果。如果命中缓存,则直接返回结果,后续步骤不再执行。
    但是缓存存在一个致命弱点:一旦这张表上发生数据变化,这个表上全部的缓存都会失效。
    所以MySQL8.0以后,整个移除了缓存模块。
  3. 分析器
    分析器进行sql语句的词法分析、语法分析。
  4. 优化器
    在表中有多个索引的时候,决定本条sql选用哪个索引。
    在多表连接的时候,决定join连接各表的顺序。
  5. 执行器
    通过分析器,MySQL知道了用户要做什么;通过优化器,MySQL知道了该怎么做最好。
    在执行器执行sql之前,需要验证用户对操作的表是否有读的权限(实际上,在分析器知道用户要做什么之后,就会进行权限验证,这里的验证操作称为precheck验证,但是precheck验证无法对运行时涉及到的表进行权限验证,比如使用了触发器的情况,因此需要在执行器之前再次验证)
    如果用户有读表的权限,执行器就会调用存储引擎提供的API接口得到数据,再验证数据是否满足条件,满足则放入结果集中。
    在这个过程中,执行器总共拿到了多少行的数据,记录在慢查询日志的rows_examined字段中。注意:某些场景下,执行器获取一行数据,引擎扫描了多行,所以,引擎扫描行数不等于rows_examined的值。

本节问题

我给你留一个问题吧,如果表 T 中没有字段 k,而你执行了这个语句 select * from T where k=1, 那肯定是会报“不存在这个列”的错误: “Unknown column ‘k’ in ‘where clause’”。你觉得这个错误是在我们上面提到的哪个阶段报出来的呢?

答案:分析器阶段报错,因为分析器在词法分析时,会对表名、字段名等字符串进行逻辑替换,将表名、字段名替换为有实际含义的程序可识别二进制码,此时就会发现,字段名无法找到实际含义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值