简单分析一下一条sql语句在MySQL中的执行流程。
MySQL的一些组件:
- 连接器:身份认证和权限相关(登录MySQL)
- 缓存器:执行查询语句时,会先查询缓存(MySQL8.0版本后移除)
- 分析器:如果缓存没命中,SQL语句就会经过分析器
- 优化器:按照MySQL认为最优的方案执行
- 执行器:执行SQL语句,从存储引擎返回数据
MySQL基本框图
客户端
即我们登录与操作MySQL所使用的终端。
连接器
用户信息验证
通过用户名和密码进行连接,若信息有误,则会收到报错信息。用户权限获取
用户名和密码正确,连接器就会读取权限表中该用户相应的权限数据,用户之后的操作,都基于此时读取到的用户权限。权限表共有4个:user,db,tables_priv,columns_priv
连接与等待超时
通过show processlist
来查看当前所有的用户连接及其行为。
Command中的字段显示该用户目前的状态,我以root登录,此时这个用户是查询状态。但若Command显示的状态是Sleep,那么说明该用户当前在等待状态。若等待超过了一段时间,则连接器会自动断开。
该超时时间由wait_timeout变量控制,可以通过show global variables like 'wait_timeout'
来查看。
MySQL默认28800秒,即8小时。
长连接与短连接
长连接
- 用户持续操作使用的是同一个连接,连接在一段时间内长时间建立。
- 可节省频繁建立连接和断开连接的开销,但所要存储的临时数据都在连接对象中,长时间积累,会导致系统内存溢出,具体表现为MySQL异常重启。
短连接
- 用户每做一些操作后就断开,下次再操作时就再进行连接。
- 与长连接相反,不用担心内存溢出的问题,但频繁建立连接和断开连接会使得效率降低。
缓存器
如果我们经过需要查询一张不常更新的表,就可能会使用到缓存器。
缓存器中使用key-value的形式存储,key值存储的是查询语句,value值存储的是对应的结果。需要注意的是,只要该表做了一次更新操作,那么该表对应的缓存就会被全部清理,因此使用场景不多。
可以通过show global variables like 'query_cache_type'
来查询缓存器是否开启。
由于我使用的是8.0以上的版本,因此该功能被移除了。
分析器
如果不使用缓存器,或者缓存器没命中,分析器就会对SQL语句进行词法分析和语法分析,了解SQL语句要“干什么”。
- 词法分析:判断SQL语句中的每一个词,如SELECT等。
- 语法分析:跟在词法分析之后,根据SQL语句的词来判断输入是否符合语法规则。
若符合规则,则会继续向下传递,否则分析器会返回报错信息。
优化器
对SQL语句的执行做优化。如,在一个SQL语句查询某个表时,该表可能有多个索引,此时使用哪个索引会使语句的执行效率最高?这就是优化器要做的事情。
执行器
在执行器执行具体的SQL语句前,会对该表的操作权限进行验证,验证失败则返回权限错误的报错信息。实际上,权限验证不仅仅在执行器这部分会做,在分析器之后,也就是知道了该语句要“干什么”之后,也会先做一次权限验证,叫precheck。而precheck是无法对运行时涉及到的表进行权限验证的,比如使用了触发器的情况。因此在执行器这里也要做一次执行时的权限验证。
如果验证成功,那么则会使用该表对应的存储引擎的接口,继续执行SQL语句。
最后将成功执行的结果返回给客户端。