mysql 查询语句执行过程

总结一下学习的 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','');
Query OK, 1 row affected (0.00 sec)

[root@localhost][mysql][09:30:07]> select * from tables_priv;
+-----------+-----------+---------------+------------+----------------------+---------------------+------------+-------------+
| Host      | Db        | User          | Table_name | Grantor              | Timestamp           | Table_priv | Column_priv |
+-----------+-----------+---------------+------------+----------------------+---------------------+------------+-------------+
| localhost | mysql     | mysql.session | user       | boot@connecting host | 0000-00-00 00:00:00 | Select     |             |
| localhost | sys       | mysql.sys     | sys_config | root@localhost       | 2019-07-26 10:56:26 | Select     |             |
| %         | codecheck | test          | t1         | root@localhost       | 0000-00-00 00:00:00 | Select     |             |
| %         | codecheck | test          | t2         | root@localhost       | 2020-06-08 09:30:07 | Select     |             |
+-----------+-----------+---------------+------------+----------------------+---------------------+------------+-------------+
4 rows in set (0.00 sec)
 

3、在 session B 中执行语句进行验证

[test@localhost][codecheck][09:25:54]> select * from t2;
ERROR 1142 (42000): SELECT command denied to user 'test'@'localhost' for table 't2'
 

4、在 session A 中刷新权限

[root@localhost][mysql][09:30:11]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

 

5、再在 session B 中进行验证

[test@localhost][codecheck][09:30:18]> select * from t2;
+------+------+
| id   | name |
+------+------+
|    2 | 1    |
|    2 | 2    |
+------+------+
2 rows in set (0.00 sec)

 

关于第二步修改权限为什么不使用 grant 语句,而是使用操作 mysql 权限表的方式:

我装的版本是 5.7.22, 测试发现 grant 是实时刷新权限的, 应该是默认 grant 就会执行权限刷新,所以达不到测试的效果。

2、关于长连接

      长连接指的是客户端与服务端一直保持连接状态的连接,容易导致OOM

      因为语句执行中使用的临时内存是由连接对象自己管理的,连接断开是才会释放

      mysql 5.7以后可通过 API 函数 mysql_reset_connection 在不断开重建的前提下,初始化长连接至刚建立时的状态

      感觉最好还是使用连接池吧,自己程序对连接进行管理工作量大了不说,还不一定比连接池做得更好。

3、关于慢日志中的 rows_examined 字段:

      该字段的值表示的是执行器调用存储引擎接口的次数累加值,并不是存储引擎扫描的行数

      这个后面学慢日志的时候可以做个实验测试。

好了,今天先写到这了,感谢~

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值