执行一条sql语句mysql都干了什么?

作为一个菜鸟程序员(我),每天会写各种各样的业务代码,不可避免的,会写到很多很多的sql语句。随着我的业务代码越来越熟练,sql语句也越写越多。那么大家有没有和我一样,有一天突然很想知道一条sql语句是怎么执行的呢?

假设我们有一个非常简单的表a,表中只有一个ID字段,那么在执行下面sql语句:

select * from a where id = 1;

mysql到底会执行一些什么操作呢?

下面是我了解到的mysql结构图,通过结构图你大概可以了解到mysql的整个执行流程

首先,你需要连接mysql的连接器(mysql -uroot -p),输入用户信息,连接器会进行用户权限校验,如果验证失败,mysql会返回错误

“Access denied for user”。

mysql通过了你的连接请求后会去查找这条sql是否有缓存,这条缓存是通过key-value的形式存在内存中的,key就是这条sql,value就是返回值

如果命中缓存,直接返回这条sql缓存的value,如果没有,这条sql会进入分析器对这条sql进行解析。

分析器会解析这条sql,首先会进行语法分析,例如我手速太快输入了一条错误的sql

selct * from a where id = 1;

分析器会先对这条sql做语法解析,很明显,mysql是看不懂selct的,这时解析器就会报错,

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 'selct * from a where id = 1' at line 1

语法通过后分析器还会根据sql的关键字去解析这条sql语句,例如select a,解析器会将a理解成一个table,where id = 1 ,解析器会将id理解成一个column等等等等

在分析器通过后,mysql还会进入优化器进行sql改写,例如选择索引,连表查询的查询先后顺序等。

优化器该写完sql就会生成sql计划去执行了,执行的时候执行器会进行一次sql执行权限的检查,在这里我就先不写demo了,因为涉及到mysql用户权限等。在权限不够的时候可能会返回一条错误。

SELECT command denied to user 'test'@'localhost' for table a

执行的时候对于不同的sql引擎执行的顺序不一样,这个问题在以后我可能会写。之后执行器就会开始去执行sql了,执行器会一行一行的和数据去比对,符合条件的会返回这一行然后继续找下一行,知道扫完整个表或者整个匹配到索引的记录。


一条sql的执行顺序大概就会经过这些流程,总结一下就是以下两种情况

  1. 连接mysql进入连接器 - 连接器验证通过查询sql缓存 - 缓存命中,直接返回缓存对应的数据

  2. 连接mysql进入连接器 - 连接器验证通过查询sql缓存 - 缓存未命中 - 进入分析器分析sql语句 - 解析通过 - 进入优化器改写sql,开始计划执行顺序 - 进入执行器 - 验证执行权限 - 执行权限通过,一行行扫描是否符合条件并返回到结果集 - 记录缓存 - 返回结果集


补充:

差点忘记了为什么大部分情况下不建议使用缓存,在这里简单说一下我的理解。

首先我们需要了解到的一点是,缓存确实可以加快查询,理由见上面的流程1。但是一条缓存在什么情况下会失效呢?当一张表执行增删改的时候,这张表的所有缓存都将被清空!在现在这种大数据时代,大部分表都是更新非常频繁的,那么当你开启缓存,很可能在缓存还未命中的情况下这条缓存就已经失效了,对于更新频繁的表来说缓存命中可能会非常低,但是由于你开启了缓存,mysql连接器连接后还是会先去查找sql缓存,结果当然很明显无法命中,之后sql才会去分析,优化,执行,执行完后还要再存一次。是不是非常没有必要?那么在什么情况下可以加sql缓存呢?一些静态表是可以做缓存的,例如系统配置表,省市区三级联动表等长期不变的表是很适合做缓存的

另外提一下在mysql8.0的时候mysql已经彻底砍掉了缓存功能了=-=可见缓存功能的鸡肋程度。还有8.0mysql也顺便废掉了不支持事务的myisam,默认引擎变成了innodb,innodb的优势我也会找机会提到。

程序幼儿员-龚学鹏
请先登录后发表评论
  • latest comments
  • 总共0条评论