总结一下学习的 mysql 语句的执行过程,不涉及具体存储引擎的执行过程。了解语句执行的过程,对与整个 mysql 的体系架构会有一个简单的整体认知,相对于后面学习的展开会有所帮助。
当我们在客户端发起一条查询语句时,对于 mysql 而言其执行的过程需要用到以下几个部分:
1、连接器
2、分析器
3、优化器
4、执行器
5、存储引擎
主要过程如下:
1、连接器对当前连接进行权限判定
如果没有权限对 sql 中的表jin进行查询则直接返回错误给客户端;
2、如果有权限,判定 mysql 是否开启了查询缓存
如果开启了,判断缓存中是否有符合条件的结果,有则直接返回
3、如果没有开启查询缓存或者查询缓存中没有找到符合条件的结果,sql 进入分析器进行分析
该阶段分析器会对 sql 的语法/语义进行判断,如果存在错误则直接返回给客户端
4、如果没有语法错误,sql 进入优化器
优化器会生成 sql 所有可能使用到的执行计划,然后在这些计划中选取执行代价最小的计划
5、优化器选出了最佳执行计划之后,执行器开始执行语句
执行器会对语句的操作权限进行判定,并调用存储引擎的接口执行语句,执行的过程大致如下:
1)、全表扫就调用存储引擎取出表的第一行数据,有索引的话则取出满足条件的第一行进行判断,如果符合条件,取出要查询的字段值放入结果集中
2)、然后调用存储引擎取下一行进行判断
3)、一直重复以上两个步骤,直到所有的可能的数据都判断完
4)、将结果集中的数据返回给客户端
6、存储引擎的作用就是根据执行计划找寻合适的数据,然后提供接口给执行器进行调用
二、补充说明:
1、关于连接器的权限判定:
权限判定所使用的是连接建立时读取到的用户所具有的权限,也就是说修改用户的权限不会影响已经建立的连接
如果有需要可执行 flush privileges 命令直接刷新权限,关于这个可以做个实验进行论证:
1、创建两个 session: session A(用 root 用户连接) 与 session B(用 test@'%' 用户连接) 2、在 session A 中对 test@‘%' 用户的权限执行变更 [root@localhost][mysql][09:29:59]> insert into tables_priv values('%','codecheck','test','t2','root@localhost',now(),'select',''); [root@localhost][mysql][09:30:07]> select * from tables_priv; 3、在 session B 中执行语句进行验证 [test@localhost][codecheck][09:25:54]> select * from t2; 4、在 session A 中刷新权限 [root@localhost][mysql][09:30:11]> flush privileges;
5、再在 session B 中进行验证 [test@localhost][codecheck][09:30:18]> select * from t2;
关于第二步修改权限为什么不使用 grant 语句,而是使用操作 mysql 权限表的方式: 我装的版本是 5.7.22, 测试发现 grant 是实时刷新权限的, 应该是默认 grant 就会执行权限刷新,所以达不到测试的效果。 |
2、关于长连接
长连接指的是客户端与服务端一直保持连接状态的连接,容易导致OOM
因为语句执行中使用的临时内存是由连接对象自己管理的,连接断开是才会释放
mysql 5.7以后可通过 API 函数 mysql_reset_connection 在不断开重建的前提下,初始化长连接至刚建立时的状态
感觉最好还是使用连接池吧,自己程序对连接进行管理工作量大了不说,还不一定比连接池做得更好。
3、关于慢日志中的 rows_examined 字段:
该字段的值表示的是执行器调用存储引擎接口的次数累加值,并不是存储引擎扫描的行数
这个后面学慢日志的时候可以做个实验测试。
好了,今天先写到这了,感谢~