MySQL 架构设计、引擎(InnoDB、MyISAM)详解

MySQL 架构、引擎详解

1.MySQL 逻辑架构

1.1 概述

那服务器进程对客户端进程发送的请求做了什么处理,才能产生最后的处理结果呢?这里以查询请求为
例展示:

展开:

1.2 详解

1.2.1 连接层

提供客户端和连接服务,包含本地 Sock 通信和大多数基于客户端/服务端工具实现的类似于 TCP/IP 的通信,主要完成一些类似于连接处理、授权认证、及相关的安全方案,在该层上引入了类似线程池的概念,为通过认证安全接入的客户端提供连接,同样在该层上可以实现基于 SSL 的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。

TCP 连接收到请求后,必须要分配给一个线程专门与这个客户端的交互。所以还会有个线程池,去走后面的流程。每一个连接从线程池中获取线程,省去了创建和销毁线程的开销。

注:分配数据库连接线程池,控制数据库的连接和关闭等资源。

1.2.2 业务逻辑处理层

主要完成大多数的核心服务功能,如 SQL 接口,并完成缓存的查询,SQL 的分析和优化及部分内置函数的操作。所有跨操作引擎的功能也在这一层实现,如过程、函数等。在该层服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定查询表的顺序、是否利用索引等,最后生成相应的执行操作。(1)

如果是 SELECT 语句,服务器还会查询内部的缓存,如果缓存空间足够大,这样在解决大量读操作的环境中能够很好的提升系统的性能。(2)

(1):在 SQL 命令传递到解析器的时候会被解析器验证和解析,并为其创建语法树,并根据数据字典丰富查询语法树,会验证该客户端是否具有执行该查询的权限 。创建好语法树后,MySQL 还会对 SQL 查询进行语法上的优化,进行查询重写。

(2):MySQL 内部维持着一些 Cache 和 Buffer,比如 Query Cache 用来缓存一条 SELECT 语句的执行结
果,如果能够在其中找到对应的查询结果,那么就不必再进行查询解析、优化和执行的整个过程了,直接将结果反馈给客户端。这个查询缓存可以在 不同客户端之间共享。

注:提供 SQL 操作的接口,对 SQL 脚本按一定规则进行解析,并通过 SQL 优化器优化执行顺序,对于查询的语句还会进入缓存区查询,提升系统的性能。

1.2.3 数据存储引擎层

插件式存储引擎层( Storage Engines),真正的负责了MySQL中数据的存储和提取,对物理服务器级别维护的底层数据执行操作,服务器通过 API 与存储引擎进行通信。不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需要进行选取。

注:存储引擎都是可插拔的,每个存储引擎所提供的服务都有所差异,所以我们需要根据具体的业务需要,选择合适的存储引擎,常用的只有两种 MyISAM 和 InnoDB。

1.2.4 数据存储层

所有的数据,数据库、表的定义,表的每一行的内容、索引,都是存在文件系统上,以文件的方式存在的,并完成与存储引擎的交互。

当然有些存储引擎比如 InnoDB,也支持不使用文件系统直接管理裸设备,但现代文件系统的实现使得这样做没有必要了。在文件系统之下,可以使用本地磁盘,可以使用DAS、NAS、SAN等各种存储系统。

注:将数据存储到磁盘上,并协同存储引擎对数据进行读写操作。

1.3 总结

简化为三层结构:

  1. 连接层:客户端和服务器端建立连接,客户端发送 SQL 至服务器端;
  2. SQL 层(服务层):对 SQL 语句进行查询处理;与数据库文件的存储方式无关;
  3. 存储引擎层:与数据库文件打交道,负责数据的存储和读取。

和其它的数据库相比,MySQL 有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用,主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离,这种架构可以根据业务的需求和实际需要选择合适的存储引擎。

2.SQL 执行流程

2.1 概述

2.2 流程详解

在 MySQL 中使用 show profiles 和 show profile for query [具体语句排序],可以查看 SQL 执行过程。

2.2.1 查询缓存

Server(服务器)如果在查询缓存中发现了这条 SQL 语句,就会直接将结果返回给客户端;如果没
有,就进入到解析器阶段。需要说明的是,因为查询缓存往往效率不高,所以在 MySQL8.0 之后就抛弃
了这个功能。(1)

(1):需要说明的是,在 MySQL 中的查询缓存,不是缓存查询计划,而是查询对应的结果。这就意味着查询匹配的鲁棒性(健壮性)大大降低 ,只有相同的查询操作才会命中查询缓存。两个查询请求在任何字符上的不同(例如:空格、注释、大小写),都会导致缓存不会命中。因此 MySQL 的查询缓存命中率不高 。

同时,如果查询请求中包含某些系统函数、用户自定义变量和函数、一些系统表,如 mysql 、 information_schema、 performance_schema 数据库中的表,那这个请求就不会被缓存。以

2.2.2 解析器

在解析器中对 SQL 语句进行语法分析、语义分析。

分析器先做“词法分析”。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。 MySQL 从你输入的"select"这个关键字识别出来,这是一个查询语句。

它也要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”。
接着,要做“语法分析”。根据词法分析的结果,语法分析器(比如:Bison)会根据语法规则,判断你输入的这个 SQL 语句是否 满足 MySQL 语法 。

如果SQL语句正确,则会生成一个这样的语法树:

其实很多计算机语言都有词法和语法分析。

2.2.3 优化器

在优化器中会确定 SQL 语句的执行路径,比如是根据全表检索 ,还是根据索引检索等。在查询优化器中,可以分为 逻辑查询优化阶段和物理查询优化阶段。

2.2.4 执行器

截止到现在,还没有真正去读写真实的表,仅仅只是产出了一个执行计划。于是就进入了执行器阶段。

在执行之前需要判断该用户是否具备权限 。如果没有,就会返回权限错误。如果具备权限,就执行 SQL 查询并返回结果。在 MySQL8.0 以下的版本,如果设置了查询缓存,这时会将查询结果进行缓存。

至此,这个语句就执行完成了。对于有索引的表,执行的逻辑也差不多。

2.2.5 总结

SQL 语句在 MySQL 中的流程是: SQL 语句→查询缓存→解析器→优化器→执行器。

3.数据库缓冲池(buffer pool)

3.1 概述

InnoDB 存储引擎是以页为单位来管理存储空间的,我们进行的增删改查操作其实本质上都是在访问页面(包括读页面、写页面、创建新页面等操作)。而磁盘 I/O 需要消耗的时间很多(1),而在内存中进行操作,效率则会高很多,为了能让数据表或者索引中的数据随时被我们所用,DBMS(数据库管理系统)会申请占用内存来作为数据缓冲池 ,在真正访问页面之前,需要把在磁盘上的页缓存到内存中的 Buffer Pool 之后才可以访问。

这样做的好处是可以让磁盘活动最小化,从而 减少与磁盘直接进行 I/O 的时间 。要知道,这种策略对提升 SQL 语句的查询性能来说至关重要。如果索引的数据在缓冲池里,那么访问的成本就会降低很多。

(1):内存和磁盘的对数据的读写速度不同,内存的速度远高于磁盘,将数据先加载到内存中,后续 CPU 对数据操作时,数据的读写会更快,效率更高。

注:数据库缓冲池和前面提到的查询缓存不是同一个东西。

3.2 组成

首先我们需要了解在 InnoDB 存储引擎中,缓冲池都包括了哪些。

在 InnoDB 存储引擎中有一部分数据会放到内存中,缓冲池则占了这部分内存的大部分,它用来存储各种数据的缓存,如下图所示:

从图中,你能看到 InnoDB 缓冲池包括了数据页、索引页、插入缓冲、锁信息、自适应 Hash 和数据字典
信息等。

3.3 过程

3.3.1 缓存原则

“位置 * 频次”这个原则,可以帮我们对 I/O 访问效率进行优化。

首先,位置决定效率,提供缓冲池就是为了在内存中可以直接访问数据。

其次,频次决定优先级顺序。因为缓冲池的大小是有限的,比如磁盘有 200G,但是内存只有 16G,缓冲池大小只有 1G,就无法将所有数据都加载到缓冲池里,这时就涉及到优先级顺序,会优先对使用频次高的热数据进行加载。

并且缓存池还会进行预读一些页面,会在读取指定页面时,将其周围的部分页面进行读取加载,提高后续的运行速度。

3.3.2 缓存池读取数据

缓冲池管理器会尽量将经常使用的数据保存起来,在数据库进行页面读操作的时候,首先会判断该页面是否在缓冲池中,如果存在就直接读取,如果不存在,就会通过内存或磁盘将页面存放到缓冲池中再进行读取。缓存在数据库中的结构和作用如下图所示:

如果我们执行 SQL 语句的时候更新了缓存池中的数据,并不会立即将数据写回磁盘中,而是写在缓存池中的页面进行更改,缓存池再以一定的频率进行数据写回到磁盘中。

当缓存池内存不够时,会进行页面的释放,释放掉在缓存池中已经修改过但还没有写回磁盘中的页面。

4.引擎介绍

4.1 InnoDB 引擎

具备外键支持功能的事务存储引擎。

  • MySQL 从 3.23.34a 版本开始就包含 InnoDB 存储引擎。大于等于5.5之后,默认采用InnoDB引擎

  • InnoDB 是 MySQL 的默认事务型引擎,它被设计用来处理大量的短期(short-lived)事务。可以确保事务
    的完整提交(Commit)和回滚(Rollback)

  • 除了增加和查询外,还需要更新、删除操作,那么,应优先选择InnoDB存储引擎

  • 除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑 InnoDB 引擎

  • 数据文件结构:

    • 表名*.frm 存储表结构(MySQL8.0时,两个结构合并在表名*.ibd中)
    • 表名*.ibd 存储数据和索引
  • InnoDB 是为处理巨大数据量的最大性能设计

    在以前的版本中,字典数据以元数据文件、非事务表等来存储。现在这些元数据文件被删除了。比如:.frm 、.par、.trn、.isl、.db、.opt等都在MySQL8.0中不存在了。

  • 对比 MyISAM 的存储引擎, InnoDB 写的处理效率差一些 ,并且会占用更多的磁盘空间以保存数据和索引

  • MyISAM 只缓存索引,不缓存真实数据;InnoDB 不仅缓存索引还要缓存真实数据,对内存要求较高 ,而且内存大小对性能有决定性的影响

4.1.1 补充
1.InnoDB 表的优势

InnoDB 存储引擎在实际应用中拥有诸多优势,比如操作便利、提高了数据库的性能、维护成本低等。如
果由于硬件或软件的原因导致服务器崩溃,那么在重启服务器之后不需要进行额外的操作。

InnoDB 崩溃恢复功能自动将之前提交的内容定型,然后撤销没有提交的进程,重启之后继续从崩溃点开始执行。

InnoDB 存储引擎在主内存中维护缓冲池,高频率使用的数据将在内存中直接被处理。这种缓存方式应用于多种信息,加速了处理进程。

在专用服务器上,物理内存中高达 80% 的部分被应用于缓冲池。如果需要将数据插入不同的表中,可以设置外键加强数据的完整性。更新或者删除数据,关联数据将会被自动更新或删除。如果试图将数据插入从表,但在主表中没有对应的数据,插入的数据将被自动移除。

如果磁盘或内存中的数据出现崩溃,在使用脏数据之前,校验和机制会发出警告。当每个表的主键都设置合理时,与这些列有关的操作会被自动优化。插入、更新和删除操作通过做改变缓冲自动机制进行优化。

InnoDB 不仅支持当前读写,也会缓冲改变的数据到数据流磁盘 。InnoDB 的性能优势不只存在于长时运行查询的大型表。在同一列多次被查询时,自适应哈希索引会提高查询的速度。使用 InnoDB 可以压缩表和相关的索引,可以在不影响性能和可用性的情况下创建或删除索引。

对于大型文本和BLOB数据,使用动态行形式,这种存储布局更高效。通过查询 INFORMATION_SCHEMA 库中的表可以监控存储引擎的内部工作。在同一个语句中,InnoDB 表可以与其他存储引擎表混用。即使有些操作系统限制文件大小为2GB,InnoDB 仍然可以处理。当处理大数据量时,InnoDB 兼顾CPU,以达到最大性能 。

2.InnoDB 和 ACID 模型

ACID模型是一系列数据库设计规则,这些规则着重强调可靠性,而可靠性对于商业数据和任务关键型应
用非常重要。MySQL包含类似InnoDB存储引擎的组件,与ACID模型紧密相连,这样出现意外时,数据不
会崩溃,结果不会失真。如果依赖ACID模型,可以不使用一致性检查和崩溃恢复机制。如果拥有额外的
软件保护,极可靠的硬件或者应用可以容忍一小部分的数据丢失和不一致,可以将MySQL设置调整为只
依赖部分ACID特性,以达到更高的性能。下面讲解InnoDB存储引擎与ACID模型相同作用的四个方面。

  1. 原子方面 ACID 的原子方面主要涉及 InnoDB 事务,与 MySQL 相关的特性主要包括:

    • 自动提交设置
    • COMMIT 语句
    • ROLLBACK 语句
    • 操作 INFORMATION_SCHEMA 库中的表数据
  2. 一致性方面 ACID 模型的一致性主要涉及保护数据不崩溃的内部InnoDB处理过程,与 MySQL 相关的特性主要包括:

    • InnoDB 双写缓存

      双写缓冲区(doublewrite buffer)是一个存储区域,InnoDB 在将页面写入 InnoDB 数据文件中的适当位置之前,会在其中写入从缓冲池中刷新的页面。如果在页面写入过程中存在操作系统、存储子系统或意外的 mysqld 进程退出,InnoDB 可以在崩溃恢复期间从双写缓冲区中找到页的完好副本。

    • InnoDB 崩溃恢复

  3. 隔离方面 隔离是应用于事务的级别,与 MySQL 相关的特性主要包括:

    • 自动提交设置。
    • SET ISOLATION LEVEL语句
    • InnoDB锁的低级别信息
  4. 耐久性方面 ACID模型的耐久性主要涉及与硬件配置相互影响的MySQL软件特性。由于硬件复杂多样化,耐久性方面没有具体的规则可循。与MySQL相关的特性有:

    • InnoDB双写缓存,通过innodb_doublewrite配置项配置
    • 配置项innodb_flush_log_at_trx_commit
    • 配置项sync_binlog
    • 配置项innodb_file_per_table
    • 存储设备的写入缓存
    • 存储设备的备用电池缓存
    • 运行MySQL的操作系统
    • 持续的电力供应
    • 备份策略
    • 对分布式或托管的应用,最主要的在于硬件设备的地点以及网络情况
3.InnoDB 架构
  1. 缓冲池:缓冲池是主内存中的一部分空间,用来缓存已使用的表和索引数据。缓冲池使得经常被使用的数据能够直接在内存中获得,从而提高速度

  2. 更改缓存:更改缓存是一个特殊的数据结构,当受影响的索引页不在缓存中时,更改缓存会缓存辅助索引页的更改。索引页被其他读取操作时会加载到缓存池,缓存的更改内容就会被合并。不同于集群索引,辅助索引并非独一无二的。当系统大部分闲置时,清除操作会定期运行,将更新的索引页刷入磁盘。更新缓存合并期间,可能会大大降低查询的性能。在内存中,更新缓存占用一部分 InnoDB 缓冲池。在磁盘中,更新缓存是系统表空间的一部分。更新缓存的数据类型由 innodb_change_buffering 配置项管理

  3. 自适应哈希索引:自适应哈希索引将负载和足够的内存结合起来,使得 InnoDB 像内存数据库一样运行,不需要降低事务上的性能或可靠性。这个特性通过 innodb_adaptive_hash_index 选项配置,或者通过 -- skip-innodb_adaptive_hash_index 命令行在服务启动时关闭

    InnoDB 会监控对表上各索引页的查询,如果观察该数据被访问的频次符合规则,那么就建立哈希索引来加快数据访问的速度,这个哈希索引称之为"Adaptive Hash Index,AHI",AHI是通过缓冲池的B+树页构建的,建立的速度很快,而且不对整颗树都建立哈希索引。(可以理解成热点的数据才会进入这个哈希表)

  4. 重做日志缓存:重做日志缓存存放要放入重做日志的数据。重做日志缓存大小通过 innodb_log_buffer_size 配置项配置。重做日志缓存会定期地将日志文件刷入磁盘。大型的重做日志缓存使得大型事务能够正常运行而不需要写入磁盘

  5. 系统表空间:系统表空间包括 InnoDB 数据字典、双写缓存、更新缓存和撤销日志,同时也包括表和索引数据。多表共享,系统表空间被视为共享表空间

  6. 双写缓存:双写缓存位于系统表空间中,用于写入从缓存池刷新的数据页。只有在刷新并写入双写缓存后,InnoDB 才会将数据页写入合适的位置

  7. 撤销日志:撤销日志是一系列与事务相关的撤销记录的集合,包含如何撤销事务最近的更改。如果其他事务要查询原始数据,可以从撤销日志记录中追溯未更改的数据。撤销日志存在于撤销日志片段中,这些片段包含于回滚片段中

  8. 每个表一个文件的表空间:每个表一个文件的表空间是指每个单独的表空间创建在自身的数据文件中,而不是系统表空间中。这个功能通过 innodb_file_per_table 配置项开启。每个表空间由一个单独的.ibd数据文件代表,该文件默认被创建在数据库目录中。

  9. 通用表空间:使用 CREATE TABLESPACE 语法创建共享的 InnoDB 表空间。通用表空间可以创建在 MySQL 数
    据目录之外能够管理多个表并支持所有行格式的表

  10. 撤销表空间:撤销表空间由一个或多个包含撤销日志的文件组成。撤销表空间的数量由 innodb_undo_tablespaces 配置项配置

  11. 临时表空间:用户创建的临时表空间和基于磁盘的内部临时表都创建于临时表空间。

    innodb_temp_data_file_path 配置项定义了相关的路径、名称、大小和属性。如果该值为空,默认会在
    innodb_data_home_dir 变量指定的目录下创建一个自动扩展的数据文件。

  12. 重做日志:重做日志是基于磁盘的数据结构,在崩溃恢复期间使用,用来纠正数据。正常操作期间,重做日志会将请求数据进行编码,这些请求会改变 InnoDB 表数据。遇到意外崩溃后,未完成的更改会自动在初始化期间重新进行

4.2 MyISAM 引擎

主要的非事务处理存储引擎。

  • MyISAM 提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等,但 MyISAM 不支持事务、行级 锁、外键 ,有一个毫无疑问的缺陷就是崩溃后无法安全恢复
  • 5.5 版本之前默认的存储引擎
  • 优势是访问的速度快 ,对事务完整性没有要求或者以 SELECT、INSERT 为主的应用
  • 针对数据统计有额外的常数存储。故而 count(*) 的查询效率很高
  • 数据文件结构:
    • 表名.frm 存储表结构
    • 表名.MYD 存储数据 (MYData)
    • 表名.MYI 存储索引 (MYIndex)
  • 应用场景:只读应用或者以读为主的业务

4.3 对比

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值