MySQL 基础架构
一, 引言
我们在学习 MySQL 的时候, 迈入 MySQL 大门的第一步就是了解并安装 MySQL 客户端, 随后才是使用 MySQL 做一系列数据库操作. 但是往往被我们忽略的却是真正了解 MySQL 基础架构, 为什么要这么说呢? 因为在对数据库数据 CURD 操作的时候, 也会出现一些问题或异常情况, 此时并不是要去盲目的解决问题, 而是直戳本质, 快速定位并解决问题.
二, MySQL 基础架构图
MySQL 基础架构可以分为两大类: Server 层和存储引擎层
Server 层: Server 层涵盖了 MySQL 大部分核心业务功能, 并且所有存储引擎的功能都在这一层实现
存储引擎层: 存储引擎有很多, 各自有着各自的特点, 可以根据场景来选择不同的存储引擎来操作数据
Server 层 | 存储引擎层 |
---|---|
三, MySQL 基础架构零件分析
连接器: 管理连接, 权限验证
分析器: 词法分析, 语法分析
查询缓存: 命中缓存, 返回结果
优化器: 执行计划生成, 索引选择
执行器: 操作引擎, 返回结果
存储引擎: 存储数据, 提供读写接口
四, 基础零件剖析
4.1 连接器
使用 MySQL 数据库, 第一步是要连接 MySQL 数据库, 这时候第一个迎接的你就是连接器. 连接器负责跟客户端建立连接, 获取权限, 管理连接等工作. 我们一般是使用命令 MySQL -uroot -p + Enter 后输入密码并登录. 当输入密码提交登录时, MySQL 客户端会与服务器建立连接, 在完成 TCP 握手后, 连接器就开始确认你所输入的用户名和密码. 如果用户名密码正确则成功登录, 如果用户名密码错误, 会受到如下错误信息!
登录失败错误信息 |
---|
登陆成功后, 连接器会对你进行权限验证, 此时权限验证都依赖于这时候读取到的权限, 并根据你的权限而赋予对数据库的操作的权力. 正是因为权限验证对验证时权限读取的依赖问题, 也反映出了如下注意点!
注意: 一个用户成功建立连接后, 即使你用管理员账号对这个用户的权限做了修改, 也不会影响已经存在连接的权限. 修改完成后, 只有再新建的连接才会使用新的权限设置.
4.2 查询缓存
连接建立完成后, 假设你正在使用该 SQL 语句查询一条数据 select * from tb_user where id = 1. 接下来 MySQL 执行逻辑就回到了查询缓存中. 此时 MySQL 拿到一个查询请求后, 先到查询缓存里看看是否执行过一这条 SQL 语句, 在之前如果执行过这条语句, 其结果大概就是以 Key-Value(键值对) 的形式直接缓存在内存中. 这里的 Key 代指的是查询语句, Value 代指的是查询结果. 如果你所查询的语句在查询缓存中就命中缓存, 它就会把该 SQL 语句对应的 value 值结果集返回, 这样就并不会执行其他 MySQL 零部件了, 大大提高了查询效率.
但是往往利弊是同时存在的, 查询缓存有着一个致命的缺点, 那就是查询缓存失效十分频繁. 这里所说的查询缓存失效是指的只要有对一个表的更新, 这个表上所有的查询缓存都会被清空. 因此可能你废了很大的劲把结果存起来, 还没使用呢, 就被一个更新全清空了! 大家都知道数据的宝贵, 由于这个致命的缺点, 导致查询缓存在 MySQL8.0 版本的时候就被抛弃了, 也就是说 MySQL8.0 版本彻底删除了查询缓存!
4.3 分析器
如果没有命中缓存, 那就必须执行 SQL 语句了. 这时候你所写的查询语句就到了分析器, 分析器先会对 SQL 语句进行 "词法分析", 它会分析并识别你所输入的空格, 字符串和关键字都在 MySQL 中代表了什么, 比如首先它会识别出来 select 关键字, 表名, 列名和条件. 识别了 SQL 语句的这些后, 就到了 "语法分析" 的阶段, 它会根据 MySQL 的语句标准来检查你所输入的 SQL 语句是否符合标准. 如果不符合标准就会报出一个 "You have an error in your SQL syntax" 的语法错误提示.
注意: 一般语法错误提示第一个你所需要关注的是紧接着 "use near" 的内容, 因为它会告诉你哪个语法附近有错误!
4.4 优化器
能进到优化器优化环节的 SQL 语句, 说明在分析器分析的时候没有出现任何错误. 那么优化器对该 SQL 语句做了些什么呢? 假如一个 SQL 语句中是有索引的, 优化器会根据优化规则选择合适的索引. 或者是一个语句夺标关联时, 优化器决定了各个表之间的连接顺序. 这里我们看一个多表连接的 SQL 语句:
select * from tb_user join tb_grade on tb_user.id = tb_grade.uid where tb_user.username = 'Ziph' and tb_grade.subject = 'Java';
先从 tb_user 表中取出 username=Ziph 的记录 ID, 再根据 ID 关联到 tb_grade 表, 再判断 tb_grade 表中的 subject 是否等于 Java
先从 tb_grade 表中取出 subject=Java 的记录 ID, 再根据 ID 关联到 tb_user 表, 再判断 tb_user 表中的 username 是否等于 Ziph
两种逻辑查询出的结果虽然是一样的, 但是执行效率会有所不同, 而优化器的作用就是根据自己的优化逻辑判断来决定使用哪一个方案
4.5 执行器
通过分析器知道了做什么, 通过优化器知道了怎么做, 这就遇到了一个问题, 谁来做? 可想而知就是执行器开始执行 SQL 语句. 开始执行的时候, 要先判断一下你对表是否有执行查询的权限, 如果没有就会报出错误的提示信息. 如果有权限, 就打开表继续执行. 执行器会根据表的引擎来调用提供的引擎接口, 开始执行.
执行器调用引擎接口执行过程: 调用 InnoDB 引擎接口取这个表的第一行, 判断是否符合查询条件, 如果不符合则跳过, 如果符合则将这行存在结果集中. 以此类推, 执行遍历所有行将所有满足条件的记录集作为结果集返回
在这里插入图片描述
来源: https://www.cnblogs.com/ziph/p/13288277.html