MySQL InnoDB 存储引擎的设计

InnoDB 存储引擎逐渐成为mysql中被广泛应用的存储引擎,其复杂的实现和操作原理对于促进最佳数据库表创建和维护至关重要。

InnoDB架构

InnoDB存储引擎包含内存池、后台线程和存储文件等关键组件。

内存池由不同的内存块组成,用作磁盘数据的缓存和缓冲重做日志。

后台线程包含主线程、IO 线程和清除线程等基本实体。

关于存储数据结构文件,InnoDB存储引擎通常包含表结构文件(.frm)、共享表空间文件(ibdata1)、独占表空间文件(ibd)和日志文件(重做文件)等文件。

内存池

我们知道,从数据库读取数据时直接从磁盘访问数据可能会带来性能瓶颈。为了解决这个问题,出现了缓存池。

当客户端读取数据时,它会检查请求的数据是否已存在于缓冲池中。如果是,则客户端直接从缓冲池中取出数据。否则,它从磁盘检索数据。当数据被修改时,首先在缓冲池内修改,然后通过Master Thread线程刷新到磁盘。

理论上,较大的缓冲池是有利的。缓冲池不仅缓存索引页和数据页,还处理回滚页、插入缓存、自适应哈希索引和 InnoDB 锁信息。

InnoDB允许使用多个缓冲池实例,减少对内部数据库资源的争用,提高数据库的并发处理能力。

为了存储redo log信息,InnoDB 存储引擎使用一个缓冲区,该缓冲区随后会刷新到redo log文件中。

后台线程

master thread主线程承担将数据从缓冲池异步刷新到磁盘的主要职责。 它还处理诸如管理插入缓存、回收回滚的操作页等任务。

另一方面,IO线程负责读写输入/输出操作,而Purge线程主要参与回收已提交的undo日志。

此外,新引入的Pager Cleaner Thread通过将脏页刷新到磁盘来协助Master Thread。 这有助于减轻主线程的工作负载并防止潜在的瓶颈。

存储文件

在MySQL中创建表时,会生成一个.frm文件,该文件用于存储每个表的元数据信息。

该文件主要包含表结构的定义。 对于InnoDB,存储的数据是根据表空间组织的。默认情况下,它使用共享表空间,对应的文件是共享表空间文件(ibdata1)。

但是,如果参数innodb_file_per_table设置为1,则数据、索引和其他信息将存储在独占表空间中,从而创建独占表空间文件(IBD)。

至于日志文件,主要由redo log日志文件组成。

这些文件主要记录事务产生的重做日志,保证事务的一致性。

InnoDB逻辑存储结构

InnoDB存储引擎采用由各种组件组成的逻辑存储结构,保证了其高效可靠的数据管理能力

  1. 表空间tablespace:InnoDB使用表空间的概念来组织和存储数据。表空间是包含表和索引的逻辑实体。默认情况下,InnoDB 使用共享表空间(由文件 ibdata1 表示)来存储数据库中的所有表和索引。但是,它还支持通过启用 innodb_file_per_table 配置参数来为每个表使用单独的表空间文件 (.ibd)。
  2. 段segments:在表空间内,数据被进一步组织成段。段是将相关数据页组合在一起的逻辑单元。 InnoDB 使用多种类型的段,包括系统段、undo 段以及每个表和索引的单独段。
  3. 范围Extents:范围是段内连续的数据页块。它们代表 InnoDB 的分配和存储单元。每个盘区包含多个数据页。
  4. 数据页data pages:数据页是InnoDB中的基本存储单元。它们存储实际的数据行和索引。 InnoDB 采用 16KB 默认页面大小,但可以根据系统要求配置为使用不同的页面大小。
  5. 索引index:InnoDB支持创建各种类型的索引来优化数据访问。这些索引存储在表空间内单独的索引段中。 InnoDB 利用 B+ 树数据结构进行高效的索引组织和检索。

通过利用这种逻辑存储结构,InnoDB 可以确保高效的数据存储、检索和管理,同时保持数据的一致性和持久性。

一次事务redo.log 如何工作?

InnoDB利用重做日志机制来保证事务的持久性和一致性。重做日志记录对数据库所做的更改,并允许在系统故障或崩溃时进行恢复。

当事务修改InnoDB中的数据时,更改首先会写入内存中的重做日志缓冲区。重做日志缓冲区事务修改写入重做日志文件之前的临时存储空间。

重做日志缓冲区通过 InnoDB Master Thread 或 Pager Cleaner Thread 定期刷新到磁盘上的redo log文件中。这个刷新过程被称为"检查点"。检查点定期或在满足某些条件时发生,以确保重做日志缓冲区中的更改写入磁盘以维持数据的持久性。

重做日志文件通常命名为 ib_logfile0 和 ib_logfile1,存储事务所做的修改的顺序记录。重做日志中的每条记录代表对特定数据页所做的更改。重做日志文件以循环方式写入,新的更改会覆盖旧的记录。

在崩溃后的恢复过程中,InnoDB使用重做日志文件来重新应用记录在重做日志缓冲区中但尚未刷新到磁盘的更改。这可确保事务正确且一致地应用于数据库,将其恢复到一致的状态。

通过采用重做日志机制,InnoDB 为已提交的事务提供持久性保证,并防止系统故障时数据丢失或不一致。

在生产环境中,启用慢SQL 监控可以揭示某些 SQL 查询中偶尔出现的延迟。

这可能是因为脏页刷新到磁盘造成的开销,导致的数据库操作的性能瓶颈。

LRU消除策略

MySQL的InnoDB存储引擎采用LRU(最近最少使用)淘汰策略来管理缓冲池,缓冲池是缓存经常访问的数据页的重要组件。

InnoDB 中的缓冲池充当缓存,用于存储从磁盘检索的数据和索引页。当缓冲池已满并且需要加载新页面时,采用LRU算法来确定应该从缓冲池中淘汰哪些页面以为新页面腾出空间。

在InnoDB中,LRU用双链表实现,其中缓冲池中的每个页面都由链表中的一个节点表示。最近访问的页面位于链表的头部,而最近最少访问的页面位于链表的尾部。

当需要淘汰页面时,会选择 LRU 列表末尾的页面(代表最近最少使用的页面)进行删除。这确保了长时间未访问的页面首先被淘汰,为更频繁访问的页面让路。

此外,为了优化LRU算法的性能,采用了中点插入策略。传统的LRU算法通常优先将最近访问的数据放置在LRU列表的最前面。然而,InnoDB 与这种方法不同,它将数据定位在中点位置,通常位于列表长度的大约 5/8 处。

这意味着当访问一个页面时,它会被移动到 LRU 列表的头部,靠近列表的中点,而不是直接移动到最前面。这有助于最大限度地减少频繁插入和删除对 LRU 列表的影响,提供更高效的淘汰过程。

通过利用LRU消除策略,InnoDB可以有效地管理缓冲池并确保保留最相关且访问最频繁的页面,从而提高系统整体性能并减少磁盘I/O操作。

这一特定策略旨在防止不常访问的操作意外取代关键的、经常访问的数据。当后续查询热数据时再次从磁盘检索热数据会影响数据库的整体查询性能。

通过调整中点值,我们可以扩大分配给热点数据的存储容量,有效降低热点数据的逐出率,增强系统保留频繁访问信息的能力。

如果喜欢这篇文章,点赞支持一下,关注我第一时间查看更多内容

相关推荐
sleP4o1 小时前
Python操作MySQL
开发语言·python·mysql
大熊程序猿1 小时前
python 读取excel数据存储到mysql
数据库·python·mysql
知识分享小能手2 小时前
mysql学习教程,从入门到精通,SQL DISTINCT 子句 (16)
大数据·开发语言·sql·学习·mysql·数据分析·数据库开发
lamb张2 小时前
MySQL锁
数据库·mysql
躺平的花卷3 小时前
Python爬虫案例六:抓取某个地区某月份天气数据并保存到mysql数据库中
数据库·爬虫·python·mysql
飞翔的佩奇5 小时前
xxl-job适配sqlite本地数据库及mysql数据库。可根据配置指定使用哪种数据库。
数据库·spring boot·mysql·sqlite·xxl-job·任务调度
如意机反光镜裸6 小时前
CentOS7安装MySQL教程
数据库·mysql
冰镇毛衣6 小时前
1.4 MySql配置文件
数据库·mysql
计算机学姐7 小时前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea
乌啼霜满天2497 小时前
如何将MySQL卸载干净(win11)
数据库·mysql