呕心沥血整理出来的mysql执行流程,一定要看!

如果用GRANT、REVOKE或SET PASSWORD对授权表进行修改,服务器会注意到并立即重新将授权表载入内存。

如果你手动地修改授权表(使用INSERT、UPDATE或DELETE等等),你应该执行mysqladmin flush-privilegesmysqladmin reload告诉服务器再装载授权表,否则你的更改将_不会生效_,除非你重启服务器。

如果你直接更改了授权表但忘记重载,重启服务器后你的更改方生效。这样可能让你迷惑为什么你的更改没有什么变化!

权限表一般在mysql库中。

user:记录允许连接到服务器的用户帐号信息,里面的权限是全局级的。

db:记录各个帐号在各个数据库上的操作权限。

table_priv:记录数据表级的操作权限。

columns_priv:记录数据列级的操作权限。

连接完成之后如果没有后续的动作,这个时候,mysql会将该链接设置为空闲状态,我们一起来看看我的mysql服务器一共有多少个客户端处于连接状态,输入命令

sqlshow processlist;

file

  • id:线程的唯一标识。
  • User:启动这个线程的用户。
  • Host:记录了发送请求的客户端IP和端口信息。
  • db:当前执行的命令发生在哪个数据库中,如果没有指定为NULL,比如我刚刚查询的sql:sqlshow processlist 并没有指定数据库,所以展示NULL。
  • Command:此刻线程正在执行的命令。
  • Time:该线程处于当前状态的时间。
  • State:线程状态,与Command对应。
  • Info:记录着线程执行的sql语句,默认展示前100个字符,如果需要查看全部,请执行 show full processlist

我们一起来看看Command一共有哪些值

  • Binlog Dump

这是复制源上的线程,用于将二进制日志内容发送到副本。

  • Change user

线程正在执行更改用户操作。

  • Close stmt

线程正在关闭准备好的语句。

  • Connect

副本连接到其源。

  • Connect Out

副本正在连接到其源。

  • Create DB

线程正在执行创建数据库操作。

  • Daemon

该线程在服务器内部,而不是为客户端连接提供服务的线程。

  • Debug

该线程正在生成调试信息。

  • Delayed insert

该线程是一个延迟的插入处理程序。

  • Drop DB

线程正在执行放置数据库操作。

  • Error

  • Execute

线程正在执行准备好的语句。

  • Fetch

线程正在从执行准备好的语句中获取结果。

  • Field List

该线程正在检索表列的信息。

  • Init DB

线程正在选择默认数据库。

  • Kill

该线程正在杀死另一个线程。

  • Long Data

执行准备好的语句的结果是线程正在检索长数据。

  • Ping

线程正在处理服务器ping请求。

  • Prepare

该线程正在准备一个准备好的语句。

  • Processlist

该线程正在生成有关服务器线程的信息。

  • Query

线程正在执行一条语句。

  • Quit

线程正在终止。

  • Refresh

该线程是刷新表,日志或缓存,或者重置状态变量或复制服务器信息。

  • Register Slave

线程正在注册副本服务器。

  • Reset stmt

该线程正在重置准备好的语句。

  • Set option

该线程正在设置或重置客户端语句执行选项。

  • Shutdown

线程正在关闭服务器。

  • Sleep

线程正在等待客户端向其发送新语句。

  • Statistics

线程正在生成服务器状态信息。

  • Time

没用过。

有点跑偏了,我们回到主题,若客户端一段时间没有使用则会被置为空闲(Sleep)状态,但如果客户端长时间没有操作,那么服务器就会自动将连接断开,默认时长 8 小时,不过可以通过 wait_timeout 参数设置。

超过时长,连接被断开之后,客户端发起请求,那么该客户端将会收到一个:Lost connection to MySQL server during query,这个时候就只能通过重新建立连接进行操作。

连接分为两种类型,一个为长连接,一个为短连接,建立连接之后,客户端发送持续请求,如果一直在同一个连接中,那么这个就是长连接,如果每个请求一个连接,则是短连接,我们知道连接会有用户信息的校验,权限的验证,比较麻烦,所以推荐使用长连接进行操作,但是长连接也不是十全十美,有利肯定就有弊,长连接过多时会导致mysql占用的内存过多,导致内存紧张,极端情况可能导致内存泄漏(OOM),那我们如何解决这个问题呢?

  1. 定时清除长连接。
  1. 通过执行 mysql_reset_connection 来重新初始化连接资源,不过要求mysql的版本在5.7或之上。

缓存

=================================================================

连接完成之后,下一步就会进入缓存,mysql会在缓存中检测之前是否执行过这条语句,如果被执行过,那么查询的结果将会以key-value的形式存储在缓存中,这个时候下一次的查询直接命中缓存,直接返回相对应的数据,如果缓存中不存在当前key(sql语句),就会进入下一个阶段 - 分析器。

mysql判断缓存是否命中的方式很简单,mysql将缓存存放在一个引用表中,通过hash值方式应用,hash值包括:查询的sql、查询的数据库、客户端协议版本等等,mysql在判断是否命中缓存的时候不会提前解析sql的语法,而是直接使用sql语句和客户端的基本信息(协议)等等,进行hash算法,这里需要特别注意:在编写sql的时候,需要与上一次执行的sql保持完全一致,空格、注释、编码或者有其他的任何不同的地方都会导致hash出来的结果不同,从而无法命中缓存,所以在操作时需要保持一个统一的编码规范。

除了这个还有很多情况也会导致查询的数据无法缓存,比如聚合函数、自定义函数、存储过、用户变量、临时表、mysql库中的系统表、权限表

mysql的缓存虽然能提升查询的性能,但是也会在其他方面造成额外的消耗,具体如下:

  1. 查询之前必须先检查是否命中缓存,对于缓存中没有的sql多了一次缓存的查询。
  1. 第一次查询或者表中的数据被修改时,当前查询需要将结果写入到缓存中,带来了额外的系统消耗。
  1. mysql在写操作时会将关于当前相关缓存的数据全部清空,如果缓存的数据过大,或者缓存的sql语句过多,可能会导致很大的系统消耗。

所以,缓存的好处可以提升查询的效率,弊端可能给系统带来额外的系统消耗,尤其是在InnoDB中的事务中,所以在使用的时候需要慎重,不可为了查询效率二盲目的使用缓存,使用不当,可能适得其反。

那mysql如何开启缓存呢?只需要将参数 query_cache_type 设置成 DEMAND 即可,这样会导致整个mysql都是使用缓存,很明显,这是不被推荐的,所以还有一种方式,那就是按需指定,什么叫按需指定呢?就是在你需要缓存的sql语句加上 SQL_CACHE 指定使用缓存即可,代码如下:

select SQL_CACHE * from sys_user where id = 1;

在这里有两点需要特别注意哦,一:mysql在8.0版本直接将缓存模块删除,也就是说,mysql8.0所有的查询都不会走向缓存了,而是直接前往磁盘;二:查询缓存的返回直接也会校验权限信息的,如果没有权限,就算使用了缓存,也无法查询。

分析(解析)器

======================================================================

mysql在缓存中没有命中之后将会进入流程的下一步,但这里并不会直接进入解析器,而是需要先将查询的sql转换成一个执行计划,在经过这个执行计划和存储引擎进行交互,这里就包括了**:解析器、预处理、优化器、执行器**。

生成完执行计划之后,mysql会对sql的关键字进行解析,生成一棵对应的 “解析树”,在这个解析过程中,mysql解析器会使用语法规则对sql进行解析和校验,第一步做的时词法分析,mysql执行的并不是你写的sql语句,而是将你写的sql语句解析成mysql可以执行的语句。

生成“解析树“之前还需要校验你的sql语句写的是否有问题,是否满足mysql的语法,如果你输入的sql语句存在问题,这个时候程序将会抛出异常,结束查询。

select * rom sys_user here id = 1;

我们故意将 from 写成了 rom,where 携程here,如果执行这条sql,程序会抛出什么异常呢?请看:

file

错误提示在rom附近存在一处语法错误,这说明,执行语法分析时,如果存在语法问题,不管有多少处问题,检测到第一处时就直接返回,不会接着往下分析,所以我们看到报错的时候别以为只有这一处问题,一定要检查仔细,否则上了生产环境,可能就会酿成大错。

接下来就需要进行预处理了,mysql会根据一些规则进一步的解析树是否合法,比如:表和数据列是否存在解析名字和别名是否存在歧义,我们再来看这条sql语句:

select * from sys_user1 here id = 1

1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘id = 1’ at line 1

时间: 0.007s

这里同样存在两处错误,第一:表名不存在,第二:关键字where写成了here,我们发现异常出现在 ”id=1“ 的附近,那么说明先分析的语法,在执行预处理的时候才校验的表名,我们现在将关键字where修改正确

select * from sys_user1 where id = 1

1142 - SELECT command denied to user ‘testlocal’@‘113.xxx.xxx.xxx’ for table ‘sys_user1’

时间: 0.006s

这个时候提示表名有问题了,说明上面的顺序,先解析sql语法,然后再预处理的时候在校验表名、字段名等是否合法。

下一步预处理还会验证权限,这里的验证一般情况下都会较快,除非权限配置相当复杂。

优化器

==================================================================

分析器完成之后,语法树已经是合法的了,这个时候优化器就登场了,优化器将这条语法树转化成执行计划。mysql官方也是很为我们开发人员着想,设置了这个优化器,在开发过程中,我们想要查询一条sql语句,执行的方式有很多,比如是否走索引、走哪条索引、关联查询哪张表做主表等等,这些都是可变的,而优化器的作用就是根据程序员写的sql语句找到一条它认为最好的执行计划。

举个例子,请看下面这条sql:

select id,user_id,username from math m join english e using(user_id)

where m.score = 80 and e.score = 90

这里不建表了,随便写了一个sql语句,大家能看明白就行,主要是讲解一下什么是优化器,math:数学成绩表;english:英语成绩表,score:成绩(字段),这条sql的意思是:查询数学成绩80分并且英语成绩90分的同学信息,你觉得mysql会怎么样执行这条sql呢?

  1. 正常情况是不是先往数学成绩表(math)中查询成绩等于80的 user_id,然后拿着这些 user_id到英语成绩表(english)中查询成绩等于90的学生信息?

  2. 能不能先前往英语成绩表(english)中查询成绩等于90的user_id,然后再去数学成绩表(math)中查询成绩等于80的学生呢?

如果数学成绩表(math)中一共有5位同学的成绩是80分,英语成绩表(english)中只有一个同学的成绩是90分,那么第二种方式是不是效率就会高很多呢?

mysql的优化器就是做这个的,他会根据独特的算法,找到它认为效率最高的一条路径去执行,这里就存在一个疑问了,经过优化器优化的sql,是否总是最优的执行计划呢?答案是否定的,哪些情况会导致优化器生成的执行计划效果反而更差呢?以下七点参考于《高性能mysql》。

  1. 统计信息不完整或者不准确,比如InnoDB的MVCC多版本并发控制会导致表数据行的统计不准确。
  1. 执行计划中的成本并不等同于实际执行的成本,这个时候即使统计的信息很准确,优化器给出的执行计划也有可能不是最优的。举个例子,有些时候某个执行嘉华虽然需要读取更多的页面或者数据,但是它的实际成本可能会很小,为什么呢?原因很简单,如果读取的页面都是有序的或者这些页面(数据)已经被加载到内存中了,这个时候的访问成本比执行计划估计的成本小得多,mysql并不知道哪些数据存在内存,哪些数据存在磁盘中,所以IO的次数也是未知数。
  1. mysql的最优可能和你想得不一样,你可能希望执行时间越短越好,但是mysql只是基于成本模型选择最优的执行计划,而有些时候这并不是最快的执行方式。所以这里我们看到的根据执行计划成本来选择执行计划并不是完美的模型。
  1. mysql从不考虑其他并发执行的查询,这可能影响到当前查询的速度。
  1. mysql并不是完全基于成本优化,有时候也会给予一些固定的规则,例如存在全文索引的match()子句,则在存在全文索引的时候就是用全文索引,即使有时候使用别的索引和where条件可以远比全文索引的方式要快很多,但是mysql也会选择使用全文索引。
  1. mysql不会考虑不受其控制的操作成本,例如存储过程或者用户自定义函数的成本。
  1. 优化器有时候无法估算所有可能的执行计划,所以它可能错过实际上最优的执行计划。

mysql的优化器是一个非常复杂的组件,算法很多优化的策略也有很多,它会通过自己的优化策略选择出优化器认为最优的一个执行计划,优化策略虽然很多,但是在大致上可以分为两种:静态优化、动态优化

静态优化:可以直接对解析树进行分析、优化。优化器可以通过代数变换将where条件转换为另外一种等价形态,这个转换不依赖条件的具体数值,即使where条件中的数值发生改变,静态优化也仍然有效。可以理解为”编译时优化“。

动态优化:它与查询的上下文相关,影响动态优化的因素有很多,比如索引对应的数量行数、where条件中的值等等,这些都会让优化器在执行sql的时候重新进行优化。可以理解为”运行时优化“。

所以优化器对sql进行优化的时候是选择静态优化还是动态优化取决于sql语句,静态优化只需要做一次,而动态优化在每次执行的时候都需要重新评估。

执行器

最后

毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节

美团面试经验

美团面试
字节面试经验
字节面试
菜鸟面试经验
菜鸟面试
蚂蚁金服面试经验
蚂蚁金服
唯品会面试经验
唯品会

因篇幅有限,图文无法详细发出
查询的上下文相关,影响动态优化的因素有很多,比如索引对应的数量行数、where条件中的值等等,这些都会让优化器在执行sql的时候重新进行优化。可以理解为”运行时优化“。

所以优化器对sql进行优化的时候是选择静态优化还是动态优化取决于sql语句,静态优化只需要做一次,而动态优化在每次执行的时候都需要重新评估。

执行器

最后

毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节

美团面试经验

[外链图片转存中…(img-T3MwlC2g-1720094596512)]
字节面试经验
[外链图片转存中…(img-cC9g6QaN-1720094596513)]
菜鸟面试经验
[外链图片转存中…(img-Ndc4eHY7-1720094596514)]
蚂蚁金服面试经验
[外链图片转存中…(img-O0AZVBhw-1720094596514)]
唯品会面试经验
[外链图片转存中…(img-P3PAETHO-1720094596515)]

因篇幅有限,图文无法详细发出

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当涉及到CAN总线的教程时,以下是一些重要的主题和步骤,希望能对你有所帮助: 1. 什么是CAN总线? CAN(Controller Area Network)总线是一种常见的实时通信协议,广泛应用于汽车、工业控制和其他领域。它允许多个节点在同一个总线上进行通信,具有高可靠性和高实时性。 2. CAN总线的基本组成 CAN总线由多个节点组成,其中包括一个或多个控制器和多个设备。控制器负责管理总线上的通信,而设备则是实际进行数据交换的节点。 3. CAN总线的通信方式 CAN总线使用一种基于事件的通信方式,即只有在节点有数据要发送时才会发送。这种方式称为事件驱动通信,可以最大程度地提高总线的利用率。 4. CAN总线的物理层 CAN总线的物理层(如电缆、传输速率等)需要根据具体应用来选择。通常使用双绞线作为传输介质,可选择不同的传输速率,例如CAN 2.0标准中的高速(1 Mbps)或低速(125 Kbps)。 5. CAN总线的帧格式 CAN总线使用帧来进行数据交换,包括标准帧和扩展帧。标准帧包含11位标识符,扩展帧则包含29位标识符。帧中还包含数据域、控制域和校验位等字段。 6. CAN总线的错误检测和纠正 CAN总线具有强大的错误检测和纠正能力。每个节点在发送数据时都会对数据进行CRC校验,并在接收数据时验证CRC以检测错误。此外,CAN总线还具有冲突检测和错误恢复机制。 7. CAN总线的应用 CAN总线广泛应用于汽车领域,用于汽车电子系统中的各种控制单元之间的通信。它还被用于工业自动化、航空航天、医疗设备等领域。 这只是一个简要的概述,如果你对CAN总线感兴趣,可以进一步深入学习相关的资料和教程。希望这些信息能够对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值