以最常用的 InnoDB 存储引擎为例进行说明。
一、核心概念:表空间 (Tablespace)
在 InnoDB 中,数据并非简单地以单个文件对应单个表,而是存储在表空间中。表空间是 InnoDB 存储数据的逻辑容器。
InnoDB 表空间的两种模式
-
系统表空间 (System Tablespace)
- 文件:通常是一个或多个名为
ibdata1,ibdata2, ... 的文件,位于 MySQL 数据目录下(如/var/lib/mysql/)。 - 存储内容:
- InnoDB 系统信息(如数据字典)。
- 双写缓冲区 (Doublewrite Buffer) 和 变更缓冲区 (Change Buffer)。
- 所有 InnoDB 表的数据和索引(如果未启用独立表空间)。
- 特点:所有表的数据都挤在一个或少数几个大文件里。缺点是无法单独收缩某个表的空间,且
ibdata1文件会不断增长,难以管理。
- 文件:通常是一个或多个名为
-
独立表空间 (File-Per-Table Tablespace)
- 文件:每个 InnoDB 表对应一个独立的
.ibd文件。 - 文件位置:位于对应数据库的目录下(如
/var/lib/mysql/mydb/mytable.ibd)。 - 存储内容:仅包含该表的数据和索引。
- 配置:通过 MySQL 配置参数
innodb_file_per_table = ON启用(现代 MySQL 版本默认开启)。 - 优点:
- 空间管理灵活:可以
TRUNCATE或DROP表来释放磁盘空间。 - 可以对单个表进行优化(如
OPTIMIZE TABLE)。 - 便于表的传输和备份。
- 空间管理灵活:可以
- 文件:每个 InnoDB 表对应一个独立的
总结:现代 MySQL 部署强烈推荐使用独立表空间模式(
innodb_file_per_table = ON)。
二、“数据库”在磁盘上的体现
在 MySQL 中,“数据库”本质上是一个命名空间或目录。
- 物理存储:
- 当你创建一个数据库(
CREATE DATABASE mydb;)时,MySQL 会在其数据目录(datadir,可通过SHOW VARIABLES LIKE 'datadir';查看)下创建一个同名的文件夹。 - 例如:
/var/lib/mysql/mydb/
- 当你创建一个数据库(
- 该文件夹内包含:
- 该数据库下所有表的
.ibd文件(在独立表空间模式下)。 - 其他相关文件,如
.frm文件(在 MySQL 8.0 之前,存储表的结构定义,即元数据)。 - 在 MySQL 8.0 及以后版本,表结构信息(数据字典)被集成到 InnoDB 的系统表空间中,不再使用
.frm文件。
- 该数据库下所有表的
简单说:一个 MySQL 数据库 ≈ 一个操作系统上的文件夹。
三、“表”在磁盘上的体现
以 InnoDB + 独立表空间 模式为例:
-
数据和索引文件:
- 每个 InnoDB 表对应一个
.ibd文件。 - 文件名:
表名.ibd(如users.ibd)。 - 位置:位于其所属数据库的文件夹内(如
/var/lib/mysql/mydb/users.ibd)。 - 内容:该文件包含了表的所有数据行和所有索引(包括主键索引、二级索引等)。InnoDB 使用 B+ 树 结构在
.ibd文件中组织数据。
- 每个 InnoDB 表对应一个
-
表结构定义文件 (MySQL 5.7 及更早版本):
- 每个表还有一个
.frm文件(如users.frm)。 - 内容:存储表的元数据,如列名、数据类型、约束、字符集等。
- 位置:同样在数据库文件夹内。
- 每个表还有一个
-
MySQL 8.0 的变化:
- 引入了数据字典 (Data Dictionary)。
- 表结构信息不再存储在
.frm文件中,而是统一存储在 InnoDB 的系统表空间(ibdata文件)的内部系统表中。 - 因此,MySQL 8.0 不再生成
.frm文件。
四、其他存储引擎的存储方式(简要)
-
MyISAM:
- 每个表有三个文件:
.frm:表结构定义。.MYD(MYData):存储数据。.MYI(MYIndex):存储索引。
- 位于数据库文件夹内。
- 每个表有三个文件:
-
Memory:
- 数据存储在内存中,不持久化到磁盘。
- 只有
.frm文件(或 MySQL 8.0 的数据字典条目)描述表结构。
五、总结:磁盘存储结构图示
假设 MySQL 数据目录为 /var/lib/mysql/,使用 InnoDB + 独立表空间 + MySQL 8.0:
/var/lib/mysql/ # MySQL 数据目录 (datadir)
├── ibdata1 # InnoDB 系统表空间 (含数据字典、双写缓冲等)
├── ib_logfile0, ib_logfile1 # InnoDB 重做日志文件
├── mysql/ # 系统数据库文件夹
│ ├── user.ibd # mysql.user 表的数据文件
│ └── ... # 其他系统表
├── performance_schema/ # performance_schema 数据库文件夹
│ └── ... # 各表的 .ibd 文件
├── mydb/ # 你的数据库 "mydb" 文件夹
│ ├── users.ibd # mydb.users 表的数据和索引文件
│ ├── orders.ibd # mydb.orders 表的数据和索引文件
│ └── products.ibd # mydb.products 表的数据和索引文件
└── ... # 其他数据库文件夹
核心要点:
- 数据库 = 文件夹。
- InnoDB 表 (8.0+) = 一个 .ibd 文件 (包含数据和索引) + 数据字典中的元数据。
- 独立表空间是现代最佳实践,便于管理和优化。
- 日志文件(如
ib_logfile*,binlog,redo log)也存储在数据目录或指定位置,对数据持久性和恢复至关重要。