参考文章:https://time.geekbang.org/column/article/68319
目录
MySQL 的逻辑架构图
连接器
查询缓存
分析器
优化器
执行器
大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。
Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB。可以通过指定存储引擎的类型来选择别的引擎,比如在 create table 语句中使用 engine=memory, 来指定使用内存引擎创建表。
长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。
短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。
建议在使用中要尽量减少建立连接的动作,也就是尽量使用长连接。但是全部使用长连接后,有些时候 MySQL 占用内存涨得特别快,这是因为 MySQL 在执行过程中临时使用的内存是管理在连接对象里面的。这些资源会在连接断开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是 MySQL 异常重启了
怎么解决这个问题呢?可以考虑以下两种方案。
1、定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。
2、如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。
MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果。
查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。
大多数情况下我会建议你不要使用查询缓存
mysql> select SQL_CACHE * from T where ID=10; //显示指定需要缓存
如果没有命中查询缓存,就要开始真正执行语句了。分析器主要明确“做什么”,验证语法的合规性,把sql转换成mysql内部识别的语句
优化器主要解决“怎么做”地问题。优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。
验证操作库表是否有权限,调用存储引擎api执行sql,得到响应结果并返回给客户端。若缓存开启,则更新缓存
-----------------------------------我是快乐且好学的分割线-----------------------------------
思考:
如果表 T 中没有字段 k,而你执行了这个语句 select * from T where k=1, 那肯定是会报“不存在这个列”的错误: “Unknown column ‘k’ in ‘where clause’”。你觉得这个错误是在我们上面提到的哪个阶段报出来的呢?
答案:分析器;根据文章分析器主要做两个事情,先做词法分析后做语法分析,词法分析主要做的是根据mysql的关键字进行验证和解析,而语法分析会在词法解析的基础上进一步做表名和字段名称的验证和解析;
-----------------------------------我是快乐且好学的分割线-----------------------------------
自问自答:
1. MySQL的框架有几个组件, 各是什么作用?
2. Server层和存储引擎层各是什么作用?
3. you have an error in your SQL syntax 这个保存是在词法分析里还是在语法分析里报错?
4. 对于表的操作权限验证在哪里进行?
5. 执行器的执行查询语句的流程是什么样的?
-----------------------------------------------------------------------------------------------------------------------------------------------------
小结:
客户端连接到服务端,获取到权限等信息, 然后在连接的有效时长内(interactive_timeout和wait_timeout参数控制, 5.7版本会断开可以自动重连)对sql进行处理。
首先会判断查询缓存是否开启,如果已经开启,会判断sql是select还是update/insert/delete,对于select,尝试去查询缓存,如果命中缓存直接返回数据给客户端, 如果缓存没有命中,或者没有开启缓存, 会进入到下一步分析器。
分析器进行语法分析、词法分析,检查sql的语法顺序等得到解析树, 然后预处理器对解析树进一步分析,验证数据表、字段是否存在,通关之后sql进入下一步优化器,所以课后问题一定是分析器阶段了。
优化器对sql执行计划分析, 得到最终执行计划,得到优化后的执行计划之后交给执行器。
执行器调用存储引擎api执行sql,得到响应结果, 将结果返回给客户端,如果缓存是开启状态, 会更新缓存。