MySQL基本组件与存储引擎
创始人
2024-06-03 10:09:18
0

文章目录

    • 一、MySQL基础架构
      • 1、Server 层基本组件介绍
      • 2、语句执行
        • 1)查询语句
        • 2)更新语句
    • 二、MySQL存储引擎
    • 三、InnoDB存储结构
    • 四、SQL执行计划

一、MySQL基础架构

image-20230312230617501

简单来说 MySQL 主要分为 Server 层和存储引擎层:

  • Server 层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binlog 日志模块。
  • 存储引擎: 主要负责数据的存储和读取,采用可以替换的插件式架构,支持 InnoDB、MyISAM、Memory 等多个存储引擎,其中 InnoDB 引擎有自有的日志模块 redolog 模块。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5 版本开始就被当做默认存储引擎了。

1、Server 层基本组件介绍

  • 连接器:主要和身份认证和权限相关的功能相关,就好比一个级别很高的门卫一样。

    主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即使管理员修改了该用户的权限,该用户也是不受影响的。

  • 查询缓存:主要用来缓存我们所执行的 SELECT 语句以及该语句的结果集。

    如果缓存 key 被命中,就会直接返回给客户端,如果没有命中,就会执行后续的操作,完成后也会把结果缓存起来,方便下一次调用。当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。MySQL 查询不建议使用缓存,因为查询缓存失效在实际业务场景中可能会非常频繁,假如你对一个表更新的话,这个表上的所有的查询缓存都会被清空。对于不经常更新的数据来说,使用缓存还是可以的。MySQL 8.0 版本后删除了缓存的功能。

  • 分析器:MySQL 没有命中缓存,那么就会进入分析器,分析器主要是用来分析 SQL 语句是来干嘛的,分析器也会分为几步:

    1. 词法分析:一条 SQL 语句有多个字符串组成,首先要提取关键字,比如 select,提出查询的表,提出字段名,提出查询条件等等
    2. 语法分析:主要就是判断你输入的 SQL 是否正确,是否符合 MySQL 的语法
  • 优化器:优化器的作用就是它认为的最优的执行方案去执行(有时候可能也不是最优),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。可以说,经过了优化器之后可以说这个语句具体该如何执行就已经定下来。

  • 执行器:当选择了执行方案后,MySQL 就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。

2、语句执行

1)查询语句

  1. 查询该语句是否有权限,如果没有权限,则直接返回错误信息;如果有权限,在8.0版本之前会先查询缓存,以SQL语句为key在内存中查询是否有结果,如果有则直接返回,没有则执行下一步

  2. 通过分析器进行词法分析,提取 SQL 语句的关键元素,比如提取上面这个语句是查询 select,提取需要查询的表名为 tb_student,需要查询所有的列,查询条件是这个表的 id=‘1’。然后判断这个 SQL 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。

  3. 接下来就是优化器进行确定执行方案,一条 SQL 语句可能有多种执行方案,如:

    a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是 18。
    b.先找出学生中年龄 18 岁的学生,然后再查询姓名为“张三”的学生。
    

    那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。

  4. 进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。

2)更新语句

  1. 先查询出要更新的数据,如果有缓存也会用到缓存,如果没有缓存则通过存储引擎进行查找,如果记录在buffer pool则直接返回,否则进入磁盘读取
  2. 执行器将查询到的数据进行更新,然后调用存储引擎接口,写入这一条数据,InnoDB引擎先在undo日志中记录,之后把数据保存在内存中,同时记录redo日志。此时redo日志的状态为prepare,然后告诉执行器执行完成了随时可以提交
  3. 执行器收到后更新binlog,然后调用引擎接口将redo日志状态更改为commit状态
  4. 更新完成

数据库崩溃时进行恢复:

  1. 如果redo log里的事务是完整的,也就是又了commit标识,则直接提交

  2. 如果redo log里的事务处于prepare状态,则判断对应的事务在binlog里是否完整

    1. 如果完整则直接提交事务

    2. 否则则使用undo log进行回滚

      因为binlog没有记录的话,从库在进行同步时无法执行这个操作,主库如果不回滚继续执行,就会导致主从不一致;同理如果binlog里的是完整的就算redo log状态不为commit也应该提交。

具体细节可以查看文章MySQL事务详解与隔离级别的实现

二、MySQL存储引擎

MySQL ⽀持多种存储引擎,你可以通过 show engines 命令来查看 MySQL ⽀持的所有存储引擎

MySQL 5.5.5 之前,MyISAM 是 MySQL 的默认存储引擎。5.5.5 版本之后,InnoDB 是 MySQL 的默认存储引擎

MySQL 存储引擎采用的是插件式架构,⽀持多种存储引擎,我们甚⾄可以为不同的数据库表设置不同的存储引擎以适应不同场景的需要。存储引擎是基于表的,而不是数据库

InnoDB与MyISAM的对比

  1. 事务:MyISAM不支持事务,InnoDB支持事务,对于InnoDB每一条语句都默认被封装成事务自动提交

  2. 锁:MyISAM只有表级锁,InnoDB支持行级锁和表级锁,默认为行级锁

  3. 外键:MyISAM不支持外键,InnoDB支持外键(一个包含外键的InnoDB表转换为MyISAM会失败)

    外键对维护数据一致性有帮助,但是对性能有一定的损耗,通常不使用外键而是在代码中进行约束

  4. 索引:MyISAM和InnoDB都是采用B+树作为索引结构,但是MyISAM是非聚集索引(索引和数据分离),而InnoDB的主键索引是聚集索引

  5. 安全:MyISAM不支持数据库崩溃后的安全恢复,而InnoDB支持(依赖于redo log)

  6. MVCC:MyISAM不支持,InnoDB支持。MyISAM连行级锁都不支持,MVCC作为行级锁的一种升级自然更不支持

  7. count:MyISAM将数据总行数存储在了磁盘,查询总行数时可以直接返回,而InnoDB数据表的行数无法预先确定(因为InnoDB的事务特性,在同一时刻表中的行数对于不同的事务而言是不一样的),因此只能在执行查询时根据当前事务进行确定,调用count时需要重新计算行数

    • count(*): 对key_len最短的二级索引进行遍历,如果没有,那么就根据聚簇索引进行遍历**(不读取聚簇索引的值)**
    • count(1):对聚簇索引进行遍历**(不读取聚簇索引的值)**
    • count(索引字段):对聚簇索引进行遍历**(读取索引的值,不统计null)**
    • count(非索引字段):全表扫描
  8. 全文索引:MyISAM支持全文索引,且查询速率更快,InnoDB5.7之前不支持全文索引

  9. 主键:MyISAM可以没有,InnoDB必须有,若没有指定则系统会自己找一列有元素都不相等的列,用这一列去组织一颗B+tree。如果不存在该列则创建一个隐藏列row_id来维护

三、InnoDB存储结构

从 InnoDB 逻辑存储结构来看,所有的数据都被逻辑的存放在一个空间中,这个空间就叫做表空间(tablespace)。**表空间由 段(segment)、区(extent)、页(page)**组成。

当我们创建一个使用InnoDB存储引擎的表后,便会在磁盘中创建一个表名.ibd文件,这就是其对应的表空间。

一个表包括索引段,数据段,回滚段等。其中索引段就是非叶子结点部分,而数据段就是叶子结点部分,回滚段用于数据的回滚和多版本控制。

一个段包含256个区,一个区对应64个数据页,一个数据页默认为 16K,一个数据区就是1MB

img

四、SQL执行计划

执行计划 是指一条 SQL 语句在经过 MySQL 查询优化器 的优化会后,具体的执行方式。

执行计划通常用于 SQL 性能分析、优化等场景。通过 EXPLAIN 的结果,可以了解到如数据表的查询顺序、数据查询操作的操作类型、哪些索引可以被命中、哪些索引实际会命中、每个数据表有多少行记录被查询等信息。

EXPLAIN 语句并不会真的去执行相关的语句,而是通过查询优化器对语句进行分析,找出最优的查询方案,并显示对应的信息。

执行结果总共有如下12列:

  1. id:一个SQL语句中可能包含多个SELECT,id就是用来标识整个查询中 SELELCT 语句的顺序。如果id相同则从上往下执行,id不同则id大的优先级高,如果引用了其他行的并集结果,则该值可以为NULL

  2. select_type:查询的类型,主要用于区分普通查询、联合查询、子查询等复杂的查询

    • SIMPLE:简单查询,不包含 UNION 或者子查询
    • PRIMARY:查询中如果包含子查询或其他部分,外层的 SELECT 将被标记为 PRIMARY。、
    • SUBQUERY:子查询中的第一个 SELECT
    • UNION:在 UNION 语句中,UNION 之后出现的 SELECT
    • DERIVED:在 FROM 中出现的子查询将被标记为 DERIVED
    • UNION RESULT:UNION 查询的结果
  3. table:查询用到的表名,每行都有对应的表名,表名除了正常的表之外,也可能是以下列出的值

    • : 本行引用了 id 为 M 和 N 的行的 UNION 结果
    • : 本行引用了 id 为 N 的表所产生的的派生表结果。派生表有可能产生自 FROM 语句中的子查询
    • : 本行引用了 id 为 N 的表所产生的的物化子查询结果
  4. partitions:匹配的分区,对于未分区的表,值为 NULL

  5. type:查询执行的类型,描述了查询是如何执行的。所有值的顺序从最优到最差排序为:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

    • system:如果表使用的引擎对于表行数统计是精确的(如:MyISAM),且表中只有一行记录的情况下,访问方法是 system ,是 const 的一种特例。
    • const:表中最多只有一行匹配的记录,一次查询就可以找到,常用于使用主键或唯一索引的所有字段作为查询条件
    • eq_ref:当连表查询时,前一张表的行在当前这张表中只有一行与之对应。是除了 system 与 const 之外最好的 join 方式,常用于使用主键或唯一索引的所有字段作为连表条件
    • ref:使用普通索引作为查询条件,查询结果可能找到多个符合条件的行
    • index_merge:当查询条件使用了多个索引时,表示开启了 Index Merge 优化,此时执行计划中的 key 列列出了使用到的索引
    • range:对索引列进行范围查询,执行计划中的 key 列表示哪个索引被使用了
    • index:查询遍历了整棵索引树,与 ALL 类似,只不过扫描的是索引,而索引一般在内存中,速度更快
    • ALL:全表扫描
  6. possible_keys:表示 MySQL 执行查询时可能用到的索引。如果这一列为 NULL ,则表示没有可能用到的索引;这种情况下,需要检查 WHERE 语句中所使用的的列,看是否可以通过给这些列中某个或多个添加索引的方法来提高查询性能。

  7. key:表示 MySQL 实际使用到的索引。如果为 NULL,则表示未用到索引。

  8. key_len:列表示 MySQL 实际使用的索引的最大长度;当使用到联合索引时,有可能是多个列的长度和。在满足需求的前提下越短越好。如果 key 列显示 NULL ,则 key_len 列也显示 NULL 。

  9. ref:当使用索引等值查询时,与索引作比较的列或常量

  10. rows:表示根据表统计信息及选用情况,大致估算出找到所需的记录或所需读取的行数,数值越小越好。

  11. filtered:按表条件过滤后,留存的记录数的百分比

  12. Extra:包含了 MySQL 解析查询的额外信息,通过这些信息,可以更准确的理解 MySQL 到底是如何执行查询的。常见的值如下:

    • Using filesort:在排序时使用了外部的索引排序,没有用到表内索引进行排序。

    • Using temporary:MySQL 需要创建临时表来存储查询的结果,常见于 ORDER BY 和 GROUP BY。

    • Using index:表明查询使用了覆盖索引,不用回表,查询效率非常高。

    • Using index condition:表示查询优化器选择使用了索引条件下推这个特性。

    • Using where:表明查询使用了 WHERE 子句进行条件过滤。一般在没有使用到索引的时候会出现。

    • Using join buffer (Block Nested Loop):连表查询的方式,表示当被驱动表的没有使用索引的时候,MySQL 会先将驱动表读出来放到 join buffer 中,再遍历被驱动表与驱动表进行查询。

      当 Extra 列包含 Using filesort 或 Using temporary 时,MySQL 的性能可能会存在问题,需要尽可能避免

参考文章:

InnoDB存储引擎对MVCC的实现 | JavaGuide(Java面试+学习指南)

Mysql_CodingALife的博客-CSDN博客

相关内容

热门资讯

122.(leaflet篇)l... 听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行...
育碧GDC2018程序化大世界... 1.传统手动绘制森林的问题 采用手动绘制的方法的话,每次迭代地形都要手动再绘制森林。这...
育碧GDC2018程序化大世界... 1.传统手动绘制森林的问题 采用手动绘制的方法的话,每次迭代地形都要手动再绘制森林。这...
Vue使用pdf-lib为文件... 之前也写过两篇预览pdf的,但是没有加水印,这是链接:Vu...
PyQt5数据库开发1 4.1... 文章目录 前言 步骤/方法 1 使用windows身份登录 2 启用混合登录模式 3 允许远程连接服...
Android studio ... 解决 Android studio 出现“The emulator process for AVD ...
Linux基础命令大全(上) ♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维...
再谈解决“因为文件包含病毒或潜... 前面出了一篇博文专门来解决“因为文件包含病毒或潜在的垃圾软件”的问题,其中第二种方法有...
南京邮电大学通达学院2023c... 题目展示 一.问题描述 实验题目1 定义一个学生类,其中包括如下内容: (1)私有数据成员 ①年龄 ...
PageObject 六大原则 PageObject六大原则: 1.封装服务的方法 2.不要暴露页面的细节 3.通过r...
【Linux网络编程】01:S... Socket多进程 OVERVIEWSocket多进程1.Server2.Client3.bug&...
数据结构刷题(二十五):122... 1.122. 买卖股票的最佳时机 II思路:贪心。把利润分解为每天为单位的维度,然后收...
浏览器事件循环 事件循环 浏览器的进程模型 何为进程? 程序运行需要有它自己专属的内存空间࿰...
8个免费图片/照片压缩工具帮您... 继续查看一些最好的图像压缩工具,以提升用户体验和存储空间以及网站使用支持。 无数图像压...
计算机二级Python备考(2... 目录  一、选择题 1.在Python语言中: 2.知识点 二、基本操作题 1. j...
端电压 相电压 线电压 记得刚接触矢量控制的时候,拿到板子,就赶紧去测各种波形,结...
如何使用Python检测和识别... 车牌检测与识别技术用途广泛,可以用于道路系统、无票停车场、车辆门禁等。这项技术结合了计...
带环链表详解 目录 一、什么是环形链表 二、判断是否为环形链表 2.1 具体题目 2.2 具体思路 2.3 思路的...
【C语言进阶:刨根究底字符串函... 本节重点内容: 深入理解strcpy函数的使用学会strcpy函数的模拟实现⚡strc...
Django web开发(一)... 文章目录前端开发1.快速开发网站2.标签2.1 编码2.2 title2.3 标题2.4 div和s...