SQL执行原理

MySQL的内部组件结构

mysql’的结构可以分成,客户端、server层,和存储引擎三个部分
在这里插入图片描述
Server层
服务层主要包括连接器查询缓存分析器优化器执行器,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。

Store层
存储引擎层负责数据的存储和提取,设计架构是可插拔的,支持InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。

连接器

mysql有非常多种类的客户端:navicat,mysql front,jdbc,SQLyog这些客户端要向mysql发起通信都必须先跟Server端建立通信连接,而建立连接的工作就是有连接器完成的。
链接数据库的命令`

[root@192 ~]# mysql ‐h host[数据库地址] ‐u root[用户] ‐p root[密码] ‐P 端口号

一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权
限。修改完成后,只有再新建的连接才会使用新的权限设置。用户的权限表在系统表空间的mysql的user表中。
修改User密码

1 mysql> CREATE USER 'username'@'host' IDENTIFIED BY 'password'; //创建新用户
2 mysql> grant all privileges on *.* to 'username'@'%'; //赋权限,%表示所有(host)
3 mysql> flush privileges //刷新数据库
4 mysql> update user set password=password(123456) where user=’root’;(设置用户名密码)
5 mysql> show grants for root@"%"; 查看当前用户的权限

连接完成以后如果不做其他的操作,那么这个链接将会处于空闲的状态可以使用命令show processlist来查看

show processlist

在这里插入图片描述

如果客户端如果长时间不发送command到Server端,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时。

1 mysql> show global variables like "wait_timeout";
2 mysql>set global wait_timeout=28800; 设置全局服务器关闭非交互连接之前等待活动的秒数

查询缓存

数据库的常用操作

 mysql>show databases; 显示所有数据库
 mysql>use dbname; 打开数据库:
 mysql>show tables; 显示数据库mysql中所有的表;
 mysql>describe user; 显示表mysql数据库中user表的列信息);

链接建立完成之后,就可以继续执行select语句了,执行逻辑就会来到第二部,查询缓存,MySql拿到某一个请求以后,会先到查询缓存中查看,在去磁盘查找,(mysql8.0以后取消了查询缓存),之前的查询结果会以key-value的形式,被直接缓存在内存中,key就是sql语句value对应的是执行的结果

在什么情况下使用查询缓存的情况比较好,数据不会经常进行增删改的情况下,查询的效率是比较好的,在数据更新比较频繁的情况下只要有对一个表的更新,这个表上所有的查询缓存都会被清空。因此很可能你费劲地把结果存起来,还没使用呢,就被一个更新全清空了。对于更新压力大的数据库来说,查询缓存的命中率会非常低。

一般建议在静态表里使用查询缓存,什么叫静态表呢?就是一般我们极少更新的表。比如,一个系统配置表、字典表,那这张表上的查询才适合使用查询缓存。好在 MySQL 也提供了这种“按需使用”的方式。你可以将my.cnf参数query_cache_type 设置成 DEMAND。

#query_cache_type有3个值 0代表关闭查询缓存OFF,1代表开启ON,2(DEMAND)代表当sql语句中有SQL_CACHE
关键词时才缓存
query_cache_type=2

查看mysql是否开启了缓存机制

mysql> show global variables like "%query_cache_type%";

监控查询缓存的命中率:

1 mysql> show status like'%Qcache%'; //查看运行的缓存信息

在这里插入图片描述
**Qcache_free_blocks:**表示查询缓存中目前还有多少剩余的blocks,如果该值显示较大,则说明查询缓存中的内存碎片过多了,可能在一定的时间进行整理。
Qcache_free_memory:查询缓存的内存大小,通过这个参数可以很清晰的知道当前系统的查询内存是否够用,是多了,还是不够用,DBA可以根据实际情况做出调整。
**Qcache_hits:**表示有多少次命中缓存。我们主要可以通过该值来验证我们的查询缓存的效果。数字越大,缓存效果越理想。
Qcache_inserts: 表示多少次未命中然后插入,意思是新来的SQL请求在缓存中未找到,不得不执行查询处理,执行查询处理后把结果insert到查询缓存中。这样的情况的次数,次数越多,表示查询缓存应用到的比较少,效果也就不理想。当然系统刚启动后,查询缓存是空的,这很正常。
Qcache_lowmem_prunes:该参数记录有多少条查询因为内存不足而被移除出查询缓存。通过这个值,用户可以适当的调整缓存大小。
**Qcache_not_cached: **表示因为query_cache_type的设置而没有被缓存的查询数量。
Qcache_queries_in_cache:当前缓存中缓存的查询数量。
Qcache_total_blocks:当前缓存的block数量。

演示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分析器

如果没有命中查询缓存,就要开始真正执行语句了。首先,MySQL 需要知道你要做什么,因此需要对 SQL 语句做解析。分析器先会做“词法分析”。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。MySQL 从你输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”。做完了这些识别以后,就要做“语法分析”。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。如果你的语句不对,就会收到“You have an error in your SQL syntax”的错误提醒,比如下面这个语句 from 写了"rom"。
词法分析器原理
1. 词法分析
2. 语法分析
3. 语义分析
4. 构造执行树
5. 生成执行计划
6. 计划的执行

在这里插入图片描述

优化器

MySQL 知道你要做什么了。在开始执行之前,还要先经过优化器的处理。优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。比如你执行下面这样的语句,这个语句是执行两个表的 join:

select * from test1 join test2 using(ID) where test1.name=yangguo and test2.name=xiaolongnv;

既可以先从表 test1 里面取出 name=yangguo的记录的 ID 值,再根据 ID 值关联到表 test2,再判断 test2 里面 name的值是否等于 yangguo。
也可以先从表 test2 里面取出 name=xiaolongnv 的记录的 ID 值,再根据 ID 值关联到 test1,再判断 test1 里面 name的值是否等于 yangguo。
这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。优化器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。如果你还有一些疑问,比如优化器是怎么选择索引的,有没有可能选择错等等。

执行器

开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下所示 (在工程实现上,如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权限)。

mysql> select * from test where id=1;

如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
比如我们这个例子中的表 test 中,ID 字段没有索引,那么执行器的执行流程是这样的:

  1. 调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 10,如果不是则跳过,如果是则将这行存在结果集中;
  2. 调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
  3. 执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
    至此,这个语句就执行完成了。对于有索引的表,执行的逻辑也差不多。第一次调用的是“取满足条件的第一行”这个接口,之后循环取“满足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。你会在数据库的慢查询日志中看到一个rows_examined 的字段,表示这个语句执行过程中扫描了多少行。这个值就是在执行器每次调用引擎获取数据行的时候累加的。在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的。

bin-log归档

什么是bin-log?
binlog是Server层实现的二进制日志,他会记录我们的cud操作。Binlog有以下几个特点:
1、Binlog在MySQL的Server层实现(引擎共用)
2、Binlog为逻辑日志,记录的是一条语句的原始逻辑
3、Binlog不限大小,追加写入,不会覆盖以前的日志

开启MySQL binlog功能
配置my.cnf

log‐bin=/usr/local/mysql/data/binlog/mysql‐bin
 注意5.7以及更高版本需要配置本项:server‐id=123454(自定义,保证唯一性);
 #binlog格式,有3种statement,row,mixed
 binlog‐format=ROW
 #表示每1次执行写入就与硬盘同步,会影响性能,为0时表示,事务提交时mysql不做刷盘操作,由系统决定
 sync‐binlog=1

binlog命令

mysql> show variables like '%log_bin%'; 查看bin‐log是否开启
mysql> flush logs; 会多一个最新的bin‐log日志
mysql> show master status; 查看最后一个bin‐log日志的相关信息
mysql> reset master; 清空所有的bin‐log日志

//查看binlog的命令
mysql> /usr/local/mysql/bin/mysqlbinlog ‐‐no‐defaults /usr/local/mysql/data/binlog/mysql‐bin.
000001 查看binlog内容
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值