Java-86 深入浅出 MySQL InnoDB磁盘结构全解析:表空间、日志系统与数据字典详解

发布于:2025-07-31 ⋅ 阅读:(25) ⋅ 点赞:(0)

点一下关注吧!!!非常感谢!!持续更新!!!

🚀 AI篇持续更新中!(长期更新)

AI炼丹日志-30-新发布【1T 万亿】参数量大模型!Kimi‑K2开源大模型解读与实践,持续打造实用AI工具指南!📐🤖

💻 Java篇正式开启!(300篇)

目前2025年07月28日更新到:
Java-83 深入浅出 MySQL 连接、线程、查询缓存与优化器详解
MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务正在更新!深入浅出助你打牢基础!

📊 大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!
大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解

请添加图片描述

InnoDB存储结构

在 MySQL 5.5 版本开始之后,默认使用 InnoDB 存储引擎,它擅长处理事务,具有自动奔溃恢复的特性,在日常开发中使用非常广泛。
下面是 InnoDB 引擎架构图,主要分为内存结构和磁盘结构两大部分。

PS:上节已经完成了内存结构的部分,本节我们继续磁盘结构

在这里插入图片描述

磁盘结构

InnoDB 存储引擎的磁盘结构是其核心组成部分,主要包含以下几个关键要素:

1. Tablespaces(表空间)

表空间是 InnoDB 存储数据的物理文件,可以分为:

  • 系统表空间:存储数据字典、双写缓冲区、变更缓冲区等元数据信息,默认文件名为 ibdata1
  • 独立表空间:每个表可以有独立的表空间文件(.ibd文件),通过 innodb_file_per_table 参数控制
  • 通用表空间:多个表可以共享同一个表空间
  • 临时表空间:存储临时表和临时数据

2. InnoDB Data Dictionary(数据字典)

数据字典包含以下元数据:

  • 表结构信息(列名、类型、索引等)
  • 表空间信息
  • 外键约束
  • 使用 InnoDB 内部系统表实现(如 SYS_TABLES, SYS_COLUMNS 等)
  • 存储在系统表空间中

3. Doublewrite Buffer(双写缓冲区)

  • 位于系统表空间中的特殊区域(默认2MB)
  • 作用:防止页写入不完整(partial page write)
  • 工作流程:
    1. 先将脏页写入双写缓冲区
    2. 再将脏页写入实际数据文件位置
    3. 确保即使发生崩溃也能从双写缓冲区恢复

4. Redo Log(重做日志)

  • 物理日志,记录对页的物理修改
  • 组成:
    • 默认2个文件:ib_logfile0ib_logfile1
    • 循环写入,大小由 innodb_log_file_size 控制
  • 作用:
    • 实现事务的持久性(Durability)
    • 崩溃恢复时重放未刷盘的修改
  • 写入流程:先写日志(WAL 原则),再修改内存中的数据页

5. Undo Log(回滚日志)

  • 逻辑日志,记录事务修改前的数据状态
  • 存储位置:
    • MySQL 5.6 以前:系统表空间
    • MySQL 5.6+:可配置独立 undo 表空间
  • 作用:
    • 事务回滚时恢复数据
    • 实现 MVCC(多版本并发控制)
    • 组成 undo 段(undo segment)管理

这些组件共同构成了 InnoDB 可靠的事务型存储引擎的基础架构,确保了 ACID 特性和高性能的并发访问能力。

表空间

Tablespaces,用于存储表结构和数据,表空间又分为白哦空间,独立表空间,通用表空间,临时表空间,Undo表空间等多种类型。

系统表空间 The System Tablespace

包含 InnoDB 数据字典,Doublewrite Buffer、Change Buffer、Undo Log的存储区域。
系统表空间也默认包含任何用户在系统表空间创建的表数据和索引数据。系统表空间是一个共享的表空间因为它是多个表共享的。该空间的数据文件通过参数 innodb_data_file_path 控制,默认值是 ibdata1:12M:autoextend

独立表空间 File-Per-Table Tablespaces

默认开启,独立表空间是一个单表表空间,该表创建于自己的数据文件中,而非创建于系统表空间中。当 innodb_file_per_table 选项开启时,表将被创建于表空间中。
否则,innodb 将被创建于系统表空间中,每个表文件空间由一个 .ibd 数据文件代表,该文件默认被创建于数据库目录中。
表空间的标文件支持动态 dynamic 和 压缩commpressed 行格式。

通用表空间 General Tablespaces

通用表空间为通过 create tablespace 语法创建爱你的共享表空间,通用表空间可以创建于 MySQL 数据目录外的其他表空间,其可以容纳多张表,且其支持所有的行格式。

PS:这个内容需要针对不同的MySQL版本处理,不同的版本不一样,可以自己查阅一下。

-- 创建通用表空间 ts1
CREATE TABLESPACE ts1 ADD DATAFILE '/var/lib/mysql/ts1.ibd' ENGINE = InnoDB;

-- 在该表空间里建表
CREATE TABLE t1 (c1 INT PRIMARY KEY) ENGINE = InnoDB TABLESPACE ts1;

在这里插入图片描述

撤销表空间 Undo Tablespaces

撤销表空间是InnoDB存储引擎中用于存储Undo日志的专用存储区域,由一个或多个包含Undo日志文件的物理文件组成。这些日志文件记录了事务修改前的数据映像,主要用于实现事务回滚和MVCC(多版本并发控制)机制。

在MySQL 5.7版本之前,Undo日志与数据字典等其他系统数据共同存储在System Tablespaces(系统表空间,默认文件名为ibdata1)的共享区域中。这种设计存在以下问题:

  1. 系统表空间会持续增长难以收缩
  2. Undo日志与其他系统数据混合存储,I/O竞争加剧
  3. 无法针对Undo日志进行单独的优化管理

从MySQL 5.7版本开始,InnoDB引入了独立的Undo表空间特性,将Undo日志从系统表空间中分离出来。这个改进带来了以下优势:

  • 独立的Undo空间管理,可以设置单独的存储策略
  • 支持在线truncate操作回收Undo空间
  • 减少系统表空间的I/O压力
  • 更容易监控Undo空间使用情况

InnoDB使用的Undo表空间数量由innodb_undo_tablespaces参数控制:

  • 默认值为0,表示仍然使用系统表空间ibdata1存储Undo日志
  • 当值设置为大于0时(通常建议设置2-128个),系统会创建独立的Undo表空间,命名为undo_001、undo_002等

典型配置示例:

# 在my.cnf配置文件中设置
[mysqld]
innodb_undo_tablespaces=8
innodb_undo_directory=/data/undologs
innodb_undo_logs=128

启用独立Undo表空间后需要注意:

  1. 需要提前创建好指定的目录并确保MySQL有写权限
  2. 修改此参数需要重启MySQL服务生效
  3. 建议将Undo表空间放在高性能存储设备上
  4. 每个Undo表空间默认初始大小为10MB,会按需自动扩展
临时表空间 Temporary Tablespaces

MySQL中的临时表空间主要用于存储临时数据,分为两种类型:

  1. Session Temporary Tablespaces

    • 存储内容:
      • 用户显式创建的临时表(通过CREATE TEMPORARY TABLE创建的表)
      • MySQL内部自动创建的临时表(如执行复杂查询时优化器创建的中间结果表)
    • 特点:
      • 每个会话(session)会创建自己的临时表空间
      • 临时表空间文件命名格式为:ibtmp1, ibtmp2等
      • 存储在数据目录下的临时表空间目录中
  2. Global Temporary Tablespaces

    • 存储内容:
      • 专门用于存储临时表的回滚段(rollback segments)
      • 管理临时表的DML操作的事务回滚信息
    • 特点:
      • 全局共享,所有会话共用
      • 用于保证临时表事务的ACID特性

生命周期管理

  • MySQL服务器正常关闭(shutdown)或异常终止(crash)时:
    • 所有临时表空间文件会被自动移除
    • 临时表中的数据会丢失(符合临时表的特性)
  • 每次MySQL服务启动时:
    • 会重新创建新的临时表空间文件
    • 初始大小由innodb_temp_data_file_path参数控制
    • 默认情况下会自动扩展

配置建议

  • 可以通过innodb_temp_data_file_path参数配置临时表空间的初始大小和增长方式
  • 在频繁使用临时表的场景下,建议适当增大临时表空间初始大小
  • 监控临时表空间使用情况,防止磁盘空间被耗尽

应用场景

  • 复杂查询排序操作
  • GROUP BY操作
  • 大表连接查询
  • 子查询优化等需要中间结果集的场景

数据字段详解:InnoDB数据字典

InnoDB Data Dictionary概述

InnoDB数据字典是MySQL存储引擎的核心组件之一,它由一系列内部系统表组成,负责存储和管理数据库对象的元数据信息。这些元数据包括但不限于:

  • 表结构定义
  • 索引信息
  • 列属性
  • 约束条件
  • 外键关系
物理存储位置

这些系统表物理存储在InnoDB的系统表空间(ibdata1文件)中。系统表空间是InnoDB用来存储系统信息的特殊表空间,包含:

  1. 数据字典元数据
  2. 变更缓冲区(Change Buffer)
  3. 双写缓冲区(Doublewrite Buffer)
  4. 撤销日志(Undo Logs)
数据字典的组成

主要系统表包括:

  • SYS_TABLES:存储表的基本信息
  • SYS_COLUMNS:记录列定义
  • SYS_INDEXES:保存索引信息
  • SYS_FIELDS:记录索引字段
  • SYS_FOREIGN:存储外键约束
历史兼容性问题

由于MySQL的历史演进,InnoDB数据字典存在以下特点:

  1. 与.frm文件重复存储:

    • 在MySQL 5.7及之前版本,表定义会同时存储在:
      • InnoDB数据字典中
      • 单独的.frm文件中
    • 这可能导致元数据不一致的问题
  2. 改进方向:

    • MySQL 8.0开始移除了.frm文件
    • 所有元数据统一存储在数据字典中
    • 采用原子DDL操作确保一致性
数据字典缓存

为提高性能,InnoDB会:

  1. 在内存中维护数据字典缓存
  2. 通过哈希表快速查找对象信息
  3. 采用LRU算法管理缓存条目
实际应用场景

当执行以下操作时都会访问数据字典:

  • 创建表(CREATE TABLE)
  • 修改表结构(ALTER TABLE)
  • 查询表信息(SHOW CREATE TABLE)
  • 优化器进行查询计划生成

双写缓冲区(Doublewrite Buffer)

双写缓冲区是InnoDB存储引擎中一个重要的数据保护机制,它位于系统表空间内,是一个特殊的存储区域。其核心功能是在将Buffer Pool中的脏页(Dirty Page)刷新到数据文件的实际位置之前,先将这些页面的数据写入到双写缓冲区。

工作原理
  1. 写入过程:当InnoDB需要将一个修改过的数据页写入磁盘时,会先将其写入双写缓冲区
  2. 双重保障:待双写缓冲区写入完成后,再将数据页写入真正的数据文件位置
  3. 崩溃恢复:如果在数据页写入过程中发生系统崩溃(如操作系统、存储子系统或MySQL进程意外终止),InnoDB在恢复时可以从双写缓冲区中找到完好的页面副本
配置参数
  • 启用/禁用:默认情况下双写缓冲区是启用的(innodb_doublewrite=1),可以通过设置innodb_doublewrite=0来禁用
  • 优化建议:当使用双写缓冲区时,建议将innodb_flush_method设置为O_DIRECT,这样可以避免操作系统缓存带来的额外开销
应用场景示例

假设一个数据库服务器正在处理交易数据:

  1. 交易数据被修改并标记为脏页
  2. 系统首先将16KB的页面完整写入双写缓冲区(通常2MB大小,可容纳128个页面)
  3. 然后将数据写入实际的数据文件位置
  4. 如果此时发生断电,恢复时可以从双写缓冲区获取完整数据
性能考量

虽然双写缓冲区会带来一定的性能开销(因为需要额外写入操作),但它提供了关键的数据保护:

  • 防止部分页写入(Partial Page Write)问题
  • 确保数据页的原子性写入
  • 对于SSD等现代存储设备,可以通过适当调优来降低性能影响

注:在完全断电保护的存储系统或某些特殊场景下,可以考虑禁用双写缓冲区,但需要充分评估数据完整性风险。

重做日志

Redo Log
重做日志是一种基于磁盘的数据结构,用于在崩溃恢复期间更正不完整事务写入的数据。MySQL以循环方式写入重做日志文件,记录InnoDB 中所有对 Buffer Pool修改的日志。
当出现实例故障,比如断电,导致数据未能更新到数据文件,则数据库重启时必须 redo,重新把数据更新到数据文件。
读写事务在执行过程中,都会不断产生 redo log。默认情况下,重做日志在磁盘上由两个 ib_logfile0 和 ib_log_file1 的文件物理表示。

撤销日志

Undo Log
撤销日志是事务开始之前保存的被修改数据的备份,用于例外情况时回滚事务。撤销日志属于逻辑日志,根据每行记录进行记录。
撤销日志存在于系统表空间、撤销表空间和临时表空间中。


网站公告

今日签到

点亮在社区的每一天
去签到