怎么做服务器当网站服务器,如何建设网站pdf,深圳网站建设公司服务,域名注册网站 简称文章目录 MySQL 基础架构分析语句分析查询语句更新语句 总结 本篇文章会分析下一个 SQL 语句在 MySQL 中的执行流程#xff0c;包括 SQL 的查询在 MySQL 内部会怎么流转#xff0c;SQL 语句的更新是怎么完成的。 MySQL 基础架构分析
下图是 MySQL 的一个简要架构图#xff… 文章目录 MySQL 基础架构分析语句分析查询语句更新语句 总结 本篇文章会分析下一个 SQL 语句在 MySQL 中的执行流程包括 SQL 的查询在 MySQL 内部会怎么流转SQL 语句的更新是怎么完成的。 MySQL 基础架构分析
下图是 MySQL 的一个简要架构图从下图你可以很清晰的看到用户的 SQL 语句在 MySQL 内部是如何执行的。
先简单介绍一下下图涉及的一些组件的基本作用帮助大家理解这幅图在后面会详细介绍到这些组件的作用。
连接器 身份认证和权限相关(登录 MySQL 的时候)。查询缓存 执行查询语句的时候会先查询缓存MySQL 8.0 版本后移除因为这个功能不太实用。分析器 没有命中缓存的话SQL 语句就会经过分析器分析器说白了就是要先看你的 SQL 语句要干嘛再检查你的 SQL 语句语法是否正确。优化器 按照 MySQL 认为最优的方案去执行。执行器 执行语句然后从存储引擎返回数据。 简单来说 MySQL 主要分为 Server 层和存储引擎层
Server 层主要包括连接器、查询缓存、分析器、优化器、执行器等所有跨存储引擎的功能都在这一层实现比如存储过程、触发器、视图函数等还有一个通用的日志模块 binlog 日志模块。存储引擎 主要负责数据的存储和读取采用可以替换的插件式架构支持 InnoDB、MyISAM、Memory 等多个存储引擎其中 InnoDB 引擎有自有的日志模块 redolog 模块。现在最常用的存储引擎是 InnoDB它从 MySQL 5.5 版本开始就被当做默认存储引擎了。
然后我们来看看server层中这些组件的具体作用 连接器 连接器主要和身份认证和权限相关的功能相关就好比一个级别很高的门卫一样。主要负责用户登录数据库进行用户的身份认证包括校验账户密码权限等操作如果用户账户密码已通过连接器会到权限表中查询该用户的所有权限之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据也就是说后续只要这个连接不断开即使管理员修改了该用户的权限该用户也是不受影响的 查询缓存(MySQL 8.0 版本后移除) 查询缓存主要用来缓存我们所执行的 SELECT 语句以及该语句的结果集。连接建立后执行查询语句的时候会先查询缓存MySQL 会先校验这个 SQL 是否执行过以 Key-Value 的形式缓存在内存中Key 是查询预计Value 是结果集。如果缓存 key 被命中就会直接返回给客户端如果没有命中就会执行后续的操作完成后也会把结果缓存起来方便下一次调用。当然在真正执行缓存查询的时候还是会校验用户的权限是否有该表的查询条件。MySQL 查询不建议使用缓存因为查询缓存失效在实际业务场景中可能会非常频繁假如你对一个表更新的话这个表上的所有的查询缓存都会被清空。对于不经常更新的数据来说使用缓存还是可以的。所以一般在大多数情况下我们都是不推荐去使用查询缓存的。MySQL 8.0 版本后删除了缓存的功能官方也是认为该功能在实际的应用场景比较少所以干脆直接删掉了 分析器 MySQL 没有命中缓存那么就会进入分析器分析器主要是用来分析 SQL 语句是来干嘛的分析器也会分为几步 第一步词法分析一条 SQL 语句有多个字符串组成首先要提取关键字比如 select提出查询的表提出字段名提出查询条件等等。做完这些操作后就会进入第二步。第二步语法分析主要就是判断你输入的 SQL 是否正确是否符合 MySQL 的语法。 完成这 2 步之后MySQL 就准备开始执行了但是如何执行怎么执行是最好的结果呢这个时候就需要优化器上场了。 优化器 优化器的作用就是它认为的最优的执行方案去执行有时候可能也不是最优这篇文章涉及对这部分知识的深入讲解比如多个索引的时候该如何选择索引多表查询的时候如何选择关联顺序等。可以说经过了优化器之后可以说这个语句具体该如何执行就已经定下来。 执行器 当选择了执行方案后MySQL 就准备开始执行了首先执行前会校验该用户有没有权限如果没有权限就会返回错误信息如果有权限就会去调用引擎的接口返回接口执行的结果。
语句分析
查询语句
说了以上这么多那么究竟一条 SQL 语句是如何执行的呢其实我们的 SQL 可以分为两种一种是查询一种是更新增加修改删除。我们先分析下查询语句语句如下
select * from tb_student A where A.age18 and A.name 张三 ;结合上面的说明我们分析下这个语句的执行流程 先检查该语句是否有权限如果没有权限直接返回错误信息如果有权限在 MySQL8.0 版本以前会先查询缓存以这条 SQL 语句为 key 在内存中查询是否有结果如果有直接缓存如果没有执行下一步。 通过分析器进行词法分析提取 SQL 语句的关键元素比如提取上面这个语句是查询 select提取需要查询的表名为 tb_student需要查询所有的列查询条件是这个表的 id‘1’。然后判断这个 SQL 语句是否有语法错误比如关键词是否正确等等如果检查没问题就执行下一步。 接下来就是优化器进行确定执行方案上面的 SQL 语句可以有两种执行方案 先查询学生表中姓名为“张三”的学生然后判断是否年龄是 18。先找出学生中年龄 18 岁的学生然后再查询姓名为“张三”的学生。 那么优化器根据自己的优化算法进行选择执行效率最好的一个方案优化器认为有时候不一定最好。那么确认了执行计划后就准备开始执行了。 进行权限校验如果没有权限就会返回错误信息如果有权限就会调用数据库引擎接口返回引擎的执行结果
更新语句
以上就是一条查询 SQL 的执行流程那么接下来我们看看一条更新语句如何执行的呢SQL 语句如下
update tb_student A set A.age19 where A.name 张三 ;我们来给张三修改下年龄。其实这条语句也基本上会沿着上一个查询的流程走只不过执行更新的时候肯定要记录日志啦这就会引入日志模块了MySQL 自带的日志模块是 binlog归档日志 所有的存储引擎都可以使用我们常用的 InnoDB 引擎还自带了一个日志模块 redo log重做日志我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下
先查询到张三这一条数据如果有缓存也是会用到缓存。然后拿到查询的语句把 age 改为 19然后调用引擎 API 接口写入这一行数据InnoDB 引擎把数据保存在内存中同时记录 redo log此时 redo log 进入 prepare 状态然后告诉执行器执行完成了随时可以提交。执行器收到通知后记录 binlog然后调用引擎接口提交 redo log 为提交状态。更新完成。
这里为什么要用两个日志模块用一个日志模块不行吗?
这是因为最开始 MySQL 并没有 InnoDB 引擎InnoDB 引擎是其他公司以插件形式插入 MySQL 的MySQL 自带的引擎是 MyISAM但是我们知道 redo log 是 InnoDB 引擎特有的其他存储引擎都没有这就导致会没有 crash-safe 的能力(crash-safe 的能力即使数据库发生异常重启之前提交的记录都不会丢失)binlog 日志只能用来归档。
并不是说只用一个日志模块不可以只是 InnoDB 引擎就是通过 redo log 来支持事务的。那么又会有同学问我用两个日志模块但是不要这么复杂行不行为什么 redo log 要引入 prepare 预提交状态这里我们用反证法来说明下为什么要这么做
先写 redo log 直接提交然后写 binlog假设写完 redo log 后机器挂了binlog 日志没有被写入那么机器重启后这台机器会通过 redo log 恢复数据但是这个时候 binlog 并没有记录该数据后续进行机器备份的时候就会丢失这一条数据同时主从同步也会丢失这一条数据。先写 binlog然后写 redo log假设写完了 binlog机器异常重启了由于没有 redo log本机是无法恢复这一条记录的但是 binlog 又有记录那么和上面同样的道理就会产生数据不一致的情况。
如果采用 redo log 两阶段提交的方式就不一样了写完 binlog 后然后再提交 redo log 就会防止出现上述的问题从而保证了数据的一致性。那么问题来了有没有一个极端的情况呢假设 redo log 处于预提交状态binlog 也已经写完了这个时候发生了异常重启会怎么样呢 这个就要依赖于 MySQL 的处理机制了MySQL 的处理过程如下
判断 redo log 是否完整如果判断是完整的就立即提交。如果 redo log 只是预提交但不是 commit 状态这个时候就会去判断 binlog 是否完整如果完整就提交 redo log, 不完整就回滚事务。
这样就解决了数据一致性的问题。
总结
我们总结一下
MySQL 主要分为 Server 层和引擎层Server 层主要包括连接器、查询缓存、分析器、优化器、执行器同时还有一个日志模块binlog这个日志模块所有执行引擎都可以共用redolog 只有 InnoDB 有。引擎层是插件式的目前主要包括MyISAM,InnoDB,Memory 等。查询语句的执行流程如下权限校验如果命中缓存---查询缓存---分析器---优化器---权限校验---执行器---引擎更新语句执行流程如下分析器----权限校验----执行器---引擎---redo log(prepare 状态)---binlog---redo log(commit 状态)