⚠️:文章记叙的顺序和阅读顺序一致。🏁 标示小知识点,需要记忆背的。💡标记代表提醒。👋标记代表了解
一、做事的道理
看一个事儿千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样能够帮助你从高维度理解问题。
基础篇:查询、修改、事务、索引、锁(全局锁、表锁、行锁)、事务隔离性。此时在想为什么事务隔离性不放在事务之后讲呢,猜测是因为事务隔离性需要了解完锁的机制才能更加深刻理解。
此处感觉基础篇讲的较少,稍后自己在看下其他的博客。
实践篇:真的更多在讲实际过程中遇到的问题,也是面试必备问题吧,就是不知道与基础篇的结合程度会有多少。
二、MySQL的基本架构
🏁:MySQL 可以分为 Server 层和存储引擎层两部分。
Server 层包括:连接器、查询缓存、分析器、优化器、执行器等。(所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。)
存储引擎层:负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。
三、分解1-连接器
🏁:1.连接器是什么?连接器负责跟客户端建立连接、获取权限、维持和管理连接。
🏁:2.如何进行连接呢?mysql -h i p − P ip -P ip−Pport -u$user -p。解释:mysql是指客户端工具主要是跟服务器建立连接。这个过程在完成TCP握手后开始进行认证你的身份,也就是后面的用户名和密码,密码通不通过是在建立连接时连接器会到权限表里面查出你拥有的权限。PS:连接建立以后,权限就确定下来。如果发生变化,需要下次重新连接时生效
🏁:3.连接完成后客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时。
PS:如何查看都有哪些客户端连接了MySQL服务器呢?show processlist;
疑问1:MySQL到底使用的是长链接还是短链接?初步猜想是长链接,待验证~
长连接和短连接的使用方式有什么不同【白痴问题】?长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。
🏁:4.MySQL为什么不采用全部是长链接的方式呢?全部使用长连接后, MySQL 占用内存涨得特别快,这是因为 MySQL 在执行过程中临时使用的内存 是 管理 在 连接对象里面的。这些资源会在连接断开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是 MySQL 异常重启了。
MySQL是怎么解决这个问题呢?此处回答了疑问1
两方面:1.定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。如果你用的是 2.MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。
四、分解2-查询缓存
连接完成后就可以执行 select 语句了
🏁:1.MySQL 拿到一个查询请求后,会先到查询缓存【key-value键值对形式】看看,之前是不是执行过这条语句,但是在8.0之后官方就去掉了。
为什么8.0后会去掉缓存呢?主要有两点,1.因为MySQL的缓存需要语句完全相同(包括参数)。2.表更新后会失效。所以使用场景就显而易见【表更新频率不高情况】
五、分解3-分析器
🏁:什么情况会走到进入分析器这一步?如果没有命中查询缓存情况下,而分析器主要包括词法分析【你的SQL每一部分「单词」代表了什么】、语法分析【】。
🏁:1.分析器主要干了什么事情?词法分析和语法分析的区别是什么?分析器主要做两个事情,先做词法分析后做语法分析,词法分析主要做的是根据mysql的关键字进行验证和解析,而语法分析会在词法解析的基础上进一步做表名和字段名称的验证和解析
六、分解4-优化器
👋:什么是优化器?优化器作用以及都做了什么?数据库就要针对你的需求想一个最优的解决方案,也就是执行计划;优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。比如你执行下面这样的语句,这个语句是执行两个表的 join:
七、分解5-执行器
🏁:执行器执行步骤【针对一个查询语句来分析】。1⃣️先判断一下你对这个表 T 有没有执行查询的权限,2⃣️如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
💡:在工程实现上,如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。
🏁:权限验证都在什么阶段会执行?为什么执行器中要做一次,分析器中也要做一次?执行器和分析器中会做权限验证;1⃣️执行器中为了校验当前客户端有没有表的权限。2⃣️在分析器最后也会先做一次权限验证。叫做precheck。而precheck是无法对运行时涉及到的表进行权限验证的,比如使用了触发器的情况。因此在执行器这里也要做一次执行时的权限验证。
⚠️:上述解释,sql执行过程中可能会有触发器这种在运行时才能确定的过程,分析器工作结束后的precheck是不能对这种运行时涉及到的表进行权限校验的,所以需要在执行器阶段进行权限检查。另外正是因为有precheck这个步骤,才会在报错时报的是用户无权,而不是 k字段不存在(为了不向用户暴露表结构)。
🏁:如何查看一条SQL执行器执行了多少次调用?存储引擎扫描了多少次?在数据库的慢查询日志中看到一个 rows_examined 的字段;在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的。
课后题:如果表 T 中没有字段 k,而你执行了这个语句 select * from T where k=1, 那肯定是会报“不存在这个列”的错误: “Unknown column ‘k’ in ‘where clause’”。你觉得这个错误是在我们上面提到的哪个阶段报出来的呢?
答案:分析器。
《高性能mysql》里提到解析器和预处理器。
解析器:处理语法和解析查询, 生成一棵对应的解析树。
预处理器:进一步检查解析树的合法。比如: 数据表和数据列是否存在, 别名是否有歧义等。如果通过则生成新的解析树,再提交给优化器。
所以我觉得课后习题的错误应该发生在在分析器处理阶段>_<