当前位置: 首页 > article >正文

【MySQL 进阶之路】InnoDB引擎详解

MySQL 进阶之路:InnoDB引擎详解

在 MySQL 的众多存储引擎中,InnoDB 是最常用的引擎之一,它支持事务、行级锁、外键等功能,适用于高并发、高数据完整性要求的场景。本篇文章将从多个维度深入解析 InnoDB 存储引擎的内部结构和原理,帮助大家更好地理解其工作机制,从而更高效地进行性能调优和问题排查。

InnoDB架构图分析

在这里插入图片描述

1. InnoDB 逻辑存储结构(Logical storage structure)

InnoDB 使用了类似于其他关系型数据库的结构来组织数据和索引。InnoDB 的逻辑存储结构包括以下几个重要部分:
在这里插入图片描述
从InnoDB的角度来看,存储引擎是以页为单位来管理存储空间的,每个表都有一个对应的逻辑空间(表空间),其中存储了表的数据和索引,表由段、区、页组成。一个区64M,一个页16K,一个区等于64个页。从MySQL 5.6版本开始,默认启用了独立表空间,每个表的数据和索引存储在单独的.ibd文件中,便于管理和维护。

段(Segment)表空间由各个段组成,创建的段类型分为数据段、索引段、回滚段等。由于 InnoDB 采用聚簇索引与 B+ 树的结构存储数据,因此事实上数据页和二级索引页仅仅只是 B+ 树的叶子节点,因此数据段称为 Leaf node segment,索引段其实指的是 B+ 树的非叶子节点,称为 Non-Leaf node segment

区(Extend): 由连续的页组成的空间,大小固定为 1MB,由于默认页大小为 16K,因此一个区默认存储 64 个连续的页。如果页大小调整为 4K,则 256 个连续页组成一个区。为了保证页的连续性,InnoDB 存储引擎会一次从磁盘申请 4 ~ 5 个区

对于新创建的独立表空间,其大小默认是 96K 而不是 1MB,这是因为在每个段开始都会使用 32 个页大小的碎片页Fragement page来存放数据,当碎片页写满了在进行 Extend 的申请,以节省磁盘容量的开销。

页(Page): InnoDB 的基本存储单位,每个页大小默认为 16K,从 InnoDB1.2.x 版本开始,可通过设置 innodb_page_size 修改为 4K、8K、16K。InnoDB 首次加载后便无法更改。InnoDB 中的页类型有数据页(B-tree Node Page)、undo 页(Undo Log Page)、系统页(System Page)、事务数据页(Transation system Page)、插入缓冲位图页(Insert Buffer Bitmap Page)、插入缓冲空闲列表页(Insert Buffer Free List)、未压缩的二进制大对象页(Uncompressed BLOB Page)、压缩的二进制大对象页(Compressed BLOB Page)。

行(row)InnoDB 是面向列(row-oriented)的关系存储引擎,因此数据是按行存储的。每个 Page 最多存放 7992 行记录。InnoDB 会为每个数据行前添加事务 ID 列(TransactionID,占 6 Byte)和回滚指针列(Roll Pointer,占 7 Byte),如果该表没有定义主键,则会选择第一个定义的非空唯一索引作为主键,若没有非空唯一索引则会在 TransactionID 前添加一列主键 ID 列(RowId,占 6 Byte)作为主键列。

组件描述
聚簇索引 (Clustered Index)表的主键索引,叶子节点存储数据行本身,索引和数据一体化。
二级索引 (Secondary Index)使用非主键列建立的索引,叶子节点存储的是主键值(而非数据行本身)。
  • 数据页 (Data Page):当查询一个表时,数据库会首先从内存中的 Buffer Pool 查找数据页,若没有找到才会从磁盘中读取。
  • 聚簇索引 (Clustered Index):聚簇索引的主键通常作为索引的键值。如果表没有显式的主键,则 InnoDB 会选择一个唯一的非空索引作为聚簇索引。
聚簇索引与二级索引

聚簇索引和二级索引之间的区别可以通过以下表格清晰展示:

特性聚簇索引二级索引
定义数据按索引顺序存储索引与数据分开存储
索引顺序决定数据的物理存储顺序与数据存储顺序无关
数量一个表只能有一个一个表可以有多个
存储方式数据和索引一起存储索引单独存储
更新开销插入、删除时需要重新排序只更新索引,数据不受影响
适用场景主键查询或范围查询非主键查询或多列查询

2. InnoDB 内存结构(Memory Structures)

InnoDB 的内存结构涉及多个层次,包括 Buffer PoolRedo Log BufferUndo Log 等,下面我们逐一讲解:

缓冲池(Buffer Pool)

在这里插入图片描述

Buffer Pool 是缓存磁盘数据页的内存区域。它的作用是减少磁盘 I/O,提高数据库性能。Buffer Pool 会将磁盘上的数据页加载到内存中,数据的读写优先从 Buffer Pool 获取。

参数说明
LRU 列表用于管理缓存的页面,最久未使用的页会被淘汰。
页的管理Buffer Pool 通过 LRU 算法来管理缓存中的数据页。
Buffer Pool 大小可以根据内存大小调整,通过 innodb_buffer_pool_size 参数设置。
  • Buffer PoolBuffer Pool 是 InnoDB 内存的核心部分,它用来缓存磁盘上的数据页,减少磁盘 I/O 操作。当数据库查询数据时,首先会在 Buffer Pool 中查找,如果数据没有命中,再从磁盘加载数据页。
    • Buffer Pool 的管理:Buffer Pool 会维护一个 LRU(最近最少使用)列表,用于管理缓存的页。当 Buffer Pool 已满时,最久未使用的页会被淘汰,以便给新的数据页腾出空间。LRU 算法有助于确保频繁访问的数据保持在内存中,提高性能。
重做缓冲区 Redo Log Buffer:

Redo Log 是 InnoDB 用来实现事务持久化的机制。所有的写操作(插入、删除、更新)都会记录在 Redo Log 中。InnoDB 会在每次事务提交时,通过 Log Buffer 将这些修改同步到磁盘中的 Redo Log 文件。

3. InnoDB 磁盘结构 (Disk Structures)

在这里插入图片描述

系统表空间(System Tablespace)

表空间类型描述
共享表空间所有数据库的表数据都存储在一个共享表空间文件中(如 ibdata1)已被删除
独立表空间每个表有独立的表空间文件(如 table_name.ibd)。
  • 系统表空间默认存储在ibdata1文件中,包含了InnoDB数据字典双写缓冲区改变缓冲区以及撤销日志(Undo Logs)等信息。
  • 在MySQL 5.6及之前的版本中,系统表空间还包含了用户数据表和索引。但从MySQL 5.7开始,用户可以通过启用innodb_file_per_table = ON参数将用户数据表和索引存储在独立的表空间中。

改变缓冲区(Change Buffer):改变缓冲区用于缓存对二级索引的更新操作。

  • 当一个二级索引页被更新时,更新操作会被写入到改变缓冲区中,而不是立即写入到磁盘上。
  • 这样可以减少磁盘I/O操作,提高性能。当需要访问这个二级索引页时,改变缓冲区中的更新操作会被合并到磁盘上的页面中。

双写缓冲 (Doublewrite Buffer):为防止因系统崩溃而造成的数据损坏,InnoDB 使用双写缓冲。数据首先写入内存中的 Doublewrite Buffer,然后再写入数据文件。

Doublewrite Buffer 确保了数据的可靠性,避免了磁盘上的脏页问题。

日志文件:InnoDB 会将所有的事务日志写入到两个重要的日志文件中:

  • Redo LogRedo Log 记录了所有修改过的数据的“redo”操作,确保即使发生崩溃也能恢复未提交的数据。Redo Log 持久化了所有的事务修改,保证了数据的持久性。
    • Redo Log 在内存中有一个 Redo Log Buffer,写入操作会先写入缓冲区,定期刷新到磁盘的日志文件中。

Redo Log 示例

-- 修改数据时,修改操作会记录到 Redo Log 中
UPDATE employees SET salary = 5000 WHERE id = 1;
Redo Log 记录了该操作,确保即使系统崩溃,也能恢复。
  • Undo LogUndo Log 是用来支持事务回滚多版本并发控制(MVCC)的关键部分。当执行修改操作时,InnoDB 会在 Undo Log 中保存修改前的旧值。若事务回滚,InnoDB 会利用 Undo Log 恢复数据。Undo Log 也用于 MVCC 的实现,支持事务隔离级别的需求。

Undo Log 示例

-- 事务回滚时,Undo Log 恢复数据
ROLLBACK;
Undo Log 将事务修改之前的数据恢复到原状态。
  • Doublewrite Buffer:为了增强数据的可靠性,InnoDB 引入了 Doublewrite Buffer。在数据写入磁盘时,首先会写入到内存中的 Doublewrite Buffer,然后再写入到数据文件。这种机制有效地避免了因电源故障等导致的脏页问题。

4. InnoDB 事务原理(Transactions)

事务是数据库管理系统的一个重要特性,InnoDB 完全支持事务,并遵循 ACID 原则。事务的管理包括以下几个方面:

ACID 原则描述
原子性事务中的操作要么全部成功,要么全部失败。通过 Undo LogRedo Log 实现。
一致性事务的执行将数据库从一个一致性状态带到另一个一致性状态。
隔离性事务间并发执行时互不干扰,每个事务是隔离的。
持久性一旦事务提交,数据会永久保存,确保数据持久性。

5. MVCC (多版本并发控制)

MVCC 是 InnoDB 实现高并发性能的关键机制,支持事务的隔离性。InnoDB 使用 MVCC 来提供读已提交可重复读等隔离级别。

  • 版本控制:InnoDB 通过在数据行中添加两个隐藏的列(DB_TRX_IDDB_ROLL_PTR)来实现版本控制。DB_TRX_ID 记录数据行最后一次更新的事务 ID,DB_ROLL_PTR 记录数据行的 Undo Log 指针。
  • 读数据的方式:当一个事务读取数据时,InnoDB 会根据事务的 快照(快照是一个事务开始时数据库的状态)来读取数据,而不是读取最新的数据版本。这样,事务就能在隔离的环境下进行操作,而不会受到其他事务的干扰。

总结

InnoDB 存储引擎是一种复杂且高效的数据库存储引擎,理解其内存结构、磁盘结构、事务原理以及 MVCC 机制,有助于我们更好地优化性能、调试问题以及设计事务管理策略。

通过深入理解 InnoDB 的工作原理,开发者可以更有针对性地进行数据库的性能优化和故障排查。无论是处理高并发场景、保证数据一致性、还是进行事务管理,InnoDB 都提供了强大的支持。

希望本篇文章能够帮助你更好地理解和掌握 InnoDB,引领你迈向 MySQL 使用和优化的进阶之路!


http://www.kler.cn/a/427768.html

相关文章:

  • 3D 生成重建015-Feature 3DGS理解3DGS场景内的一切
  • 软件工程——期末复习(4)
  • 同道猎聘Q3营收降利润增,AI或成估值重塑关键词
  • JAVA设计模式,工厂模式
  • gitlab-cicd部署安装与具体操作
  • 在visio2021 中插入MathType公式
  • 【bug】pymysql.err.OperationalError: (1046, ‘No database selected‘)
  • React16搭建-GPT回答
  • 游戏引擎学习第36天
  • [Flutter]Json序列化json_serializable使用属性全介绍
  • 嵌入式蓝桥杯学习4 lcd移植
  • 【Linux】09 -- Linux下的shell编程(一)
  • 针对xpath局限的解决方案
  • 室联人形机器人:家政服务任务结构化、技术要点、深入应用FPGA的控制系统框架设计(整合版)
  • docker 安装mysql8.0.29
  • 【Leetcode Top 100 - 扩展】876. 链表的中间结点
  • OpeAI大模型学习(一)
  • WPF Prism ViewDiscovery
  • Python机器学习笔记(五、决策树集成)
  • 以攻击者的视角进行软件安全防护