在Mysql中执行一条SQL,会经历什么?

背景

咱们都常用Mysql做为数据库来存储与查询较经常使用的数据。当咱们输入一行如SELECT * FROM table_name WHERE id=26这样的语句以后,Mysql若是正确执行的状况下,会输出你想要的信息。mysql

那么,在你输入这行语句以后,一直到它显示出你想要的信息,这中间Mysql都经历了什么呢?这篇文章会简单聊一下这个事情。sql

Mysql基本架构图

咱们先看下Mysql的一个较总体的架构图。数据库

接下来我会以具体的SQL语句为例,详细的叙述从你在客户端输入了这个语句以后,到它返回你想要的信息,这中间具体经历了什么。缓存

客户端

所谓客户端,便是咱们登陆与操做Mysql所使用的终端。咱们都是在客户端对Mysql进行操做的,不管是输入链接数据库的信息,仍是输入查询某个表的SQL,或者是收到Mysql返回给咱们的查询信息,这些都是在客户端完成的。markdown

链接器

用户信息验证

咱们在一个客户端跟前,想要使用Mysql数据库,那么第一步就是要先链接上你要使用的数据库。架构

咱们都知道,咱们要输入命令mysql -h$ip -P$port -u$username -p优化

以后客户端会要求咱们输入密码。再以后,若是咱们输入的信息都没有问题了,咱们就进入Mysql的操做界面了。spa

若是咱们输入的信息有问题,就会收到客户端返回的报错信息。好比咱们将密码输入错误了,这时就会收到"Access denied for user"这样的报错信息。code

那么,这中间链接器具体作了什么呢?orm

首先,链接器会拿着咱们输入的IP和端口,去作最经典的TCP握手,握手若是都失败了,那就天然没有后续了,直接返回相应的报错信息。

若是握手成功了,此时则会去验证咱们输入的用户名和密码,验证失败则一样会返回相应的报错信息。

用户权限获取

若是用户名密码也没有问题,接下来链接器则会取出权限表读取该用户相应的权限数据。用户跟着所作的全部操做,都基于此时读取到的用户权限。

权限表共有4个:user, db, tables_priv, columns_priv

当用户经过权限验证,进行权限分配时,按照user, db, tables_priv, columns_priv的顺序进行分配。即先检查用户的全局权限表user,若是user中对应的权限为Y,则此用户对全部数据库的权限都为Y,将再也不检查剩余3个表;若是为N,则到db表中检查此用户对应的具体数据库,并获得db中为Y的权限;若是db中为N,则检查tables_priv中此数据库对应的具体表,取得表中的权限Y;若是为N,则到columns_priv中检查具体的列。

这也就意味着,当咱们修改了某个用户的用户权限,只有到下一次该用户登陆(建立新的链接)时,才会影响到该用户。

链接与等待超时

咱们能够经过show processlist来查看当前全部的用户链接及其行为。

Command中的字段显示该用户目前的状态,此时这个用户是查询状态。

但若Command显示的状态是Sleep,那么说明该用户当前在等待状态。若等待超过了一段时间,则链接器会自动断开。

该超时时间由wait_timeout变量控制,能够经过show global variables like 'wait_timeout'来查看。

mysql默认为28800秒,即8小时。

长链接与短链接

所谓长链接,即用户的持续操做使用的都是同一个链接,链接在一段时间内长时间创建。

所谓短链接,即用户每作几回操做则断开,再下次操做时再进行链接。

长链接的优势是,在持续操做时,能够节省不少创建链接所须要消耗的时间。可是长链接所要存储的临时数据都在链接对象中,长时间积累,会致使系统内存溢出,具体表现 为Mysql异常重启。

短链接的优缺点与长链接相反,虽然不用担忧内存溢出的问题,但短链接在持续操做的状况下屡次链接,链接消耗不少时间,总体操做效率会很低。

缓存器

链接器链接完成的下一步就是缓存器的缓存查询,若是咱们须要对一张静态表(不常更新)常常作查询操做,那么可能会用到缓存器。

缓存器中使用的是key-value的存储形式,key值存储的是查询语句,value值存储的是对应结果。

要注意的是,只要该表作了一次更新操做,那么该表对应的缓存就会所有被清理。所以使用场景并很少。

因此当前缓存器的使用较少。咱们能够经过query_cache_type来查看缓存器是否开启。

如今通常都是默认关闭的状态。且Mysql从8.0版本会开始完全弃用该功能。

分析器

假设咱们不使用缓存器,或者经过缓存器没有命中SQL语句。

那么链接器作链接操做以后,接下来咱们就输入了一个查询语句,好比:SELECT host FROM mysql.user LIMIT 1

而分析器作的事情就是对你输入的语句作 “词法分析”“语法分析”

所谓 “词法分析” ,就是判断每个你输入的词,好比分析器首先会判断出你输入的第一个词是“SELECT”,第二个词你输入了“host”,等等。

“语法分析” 则是跟在 “词法分析” 以后,就是依据你输入的这些词来判断你输入的是否符合语法规则。

假如符合语法规则,则会顺利进行下去并返回相应信息。

假如不符合语法规则,则分析器会返回报错信息给客户端。
具体出错的地方,通常都是跟在use near以后,咱们看这里就能知道语法错误出在了哪一块。

优化器

在分析器工做结束后,若是语法有问题,那么就会直接返回报错信息,且不继续向下运行。

若语法正确,那么,则会到优化器部分的工做。优化器顾名思义,就是对该语句的执行作优化。

好比,在一个语句查询某个表时,该表可能有多个索引,此时使用哪一个索引会使语句的执行效率最高?这就是优化器要作的事情。

再好比,执行语句select * from t1 join t2 on t1.ID=1 and t2.ID=2

该语句执行时,是先从t1表中找到ID=1的行关联到t2表以后,再从t2表中查找ID=2的行。

仍是先从t2表中找到ID=2的行关联到t1表以后,再从t1表中查找ID=1的行。

两种执行顺序可能就致使执行效率的不一样,怎样选择执行顺序会提升执行效率,这也是优化器要作的事情。

执行器

在上述步骤完成以后,就轮到执行器去执行具体的语句了。

例如语句:select * from mysql.tables_priv

在执行器作具体的语句执行以前,会对该表的操做权限进行验证,验证失败则返回权限错误的报错。以下:

而实际上,权限验证不只仅在执行器这部分会作,在分析器以后,也就是知道了该语句要“干什么”以后,也会先作一次权限验证。叫作precheck。

而precheck是没法对运行时涉及到的表进行权限验证的,好比使用了触发器的状况。所以在执行器这里也要作一次执行时的权限验证。

若是验证成功,那么则会使用该表对应的存储引擎的接口,继续执行语句。 最后将成功执行的结果返回给客户端。

总结

简单来讲,一条SQL语句在Mysql中执行,一共会经历四步(算上链接Mysql),分别是链接、分析、优化与执行。每一步都会精确执行,若是发现有问题就会返回给客户端相应的报错。只有每一步都正确执行,最终才会在客户端获得你想要查询或操做的结果。

相关文章
相关标签/搜索