mysql部分概念解答(索引、事务数据字典、MVCC、单表文件表空间与通用表空间、元数据、重做日志和还原日志)
在学习mysql的过程中,为了更好的理解其架构,下面我将对其中部分易混淆的概念进行解答。
文章目录:
目录
一、索引
索引的主要作用
常见的索引类型
索引的优缺点
索引具体如何工作的?为什么加了索引后对数据的操作变快了?
原本的存储方式(无索引)
存储特点:
示例:
加了索引之后的存储方式
存储特点:
示例:
为什么加了索引之后变快了?
二、事务数据字典
事务数据字典的主要功能
事务数据字典的常见内容
事务数据字典的实现
示例:MySQL 中的事务数据字典
示例:Oracle 中的事务数据字典
事务数据字典的优势
三、元数据
四、单表文件表空间和通用表空间
1. 单表文件表空间(File-Per-Table Tablespace)
特点:
启用方式:
优点:
缺点:
示例:
2. 通用表空间(General Tablespace)
特点:
创建通用表空间:
将表添加到通用表空间:
优点:
缺点:
示例:
单表文件表空间 vs 通用表空间
五、MVCC
MVCC 的核心思想
MVCC 的工作原理
MVCC 的优点
MVCC 的缺点
MVCC 的实现
示例:MYSQL 中的 MVCC
六、重做日志和还原日志
1. 重做日志(Redo Log)
2. 还原日志(Undo Log)
3. 重做日志与还原日志的区别
4. 协同工作
5. 实际应用
一、索引
索引是数据库中用于加快数据检索速度的数据结构,类似于书籍的目录。它通过建立特字段的引用,帮助数据库快速定位,而不必扫描整个表。
索引的主要作用
-
加速查询:显著提高
SELECT
查询的速度。 -
加速排序和分组:提升
ORDER BY
和GROUP BY
操作的效率。 -
保证唯一性:唯一索引确保某列的值不重复。
-
加速连接操作:提高表连接(
JOIN
)的速度。
常见的索引类型
-
单列索引:基于单个列创建。
CREATE INDEX idx_name ON table_name (column_name);
-
复合索引:基于多个列创建。
CREATE INDEX idx_name ON table_name (column1, column2);
-
唯一索引:确保列中的值唯一。
CREATE UNIQUE INDEX idx_name ON table_name (column_name);
-
主键索引:特殊的唯一索引,不允许
NULL
值。ALTER TABLE table_name ADD PRIMARY KEY (column_name);
-
全文索引:用于全文搜索,适用于文本数据。
CREATE FULLTEXT INDEX idx_name ON table_name (column_name);
-
空间索引:用于地理空间数据。
CREATE SPATIAL INDEX idx_name ON table_name (column_name);
索引的优缺点
优点:
-
显著提高查询速度。
-
加速排序和分组操作。
-
保证数据唯一性。
缺点:
-
占用额外存储空间。
-
降低数据插入、更新、删除的速度,因为索引需要同步更新
索引具体如何工作的?为什么加了索引后对数据的操作变快了?
原本的存储方式(无索引)
在没有索引的情况下,数据库通常以 堆表(Heap Table) 的方式存储数据。数据行按插入顺序存储,查询时需要通过 全表扫描(Full Table Scan) 逐行查找匹配的数据。
存储特点:
-
无序存储:数据按插入顺序存储,物理上没有特定的顺序。
-
全表扫描:查询时,数据库需要逐行扫描整个表,直到找到匹配的数据。
-
时间复杂度:查找操作的时间复杂度为 O(n),其中 n 是表中的行数。当数据量很大时,查询效率会显著下降。
示例:
假设有一个 users
表,包含以下数据:
id | name | age |
---|---|---|
1 | Alice | 25 |
2 | Bob | 30 |
3 | Charlie | 22 |
4 | David | 28 |
如果执行以下查询:
SELECT * FROM users WHERE name = 'Bob';
数据库需要逐行扫描整个表,直到找到 name = 'Bob'
的行。
加了索引之后的存储方式
索引是一种 数据结构,它通过额外的存储空间来维护表中某些列的快速查找路径。常见的索引类型是 B+树索引。
存储特点:
-
有序存储:索引会根据索引列的值对数据进行排序,并建立一种高效的查找结构(如 B+树)。
-
快速查找:查询时,数据库可以通过索引快速定位到目标数据,而不需要扫描整个表。
-
时间复杂度:查找操作的时间复杂度为 O(log n),其中 n 是表中的行数。对于大数据集,索引可以显著提高查询效率。
示例:
在 users
表的 name
列上创建索引:
CREATE INDEX idx_name ON users (name);
索引会生成一个类似以下的结构(以 B+树为例):
Root ├── Alice ├── Bob ├── Charlie └── David
当执行以下查询时:
SELECT * FROM users WHERE name = 'Bob';
数据库会使用索引 idx_name
快速定位到 name = 'Bob'
的行,而不需要扫描整个表。
为什么加了索引之后变快了?
-
减少数据扫描量:
-
无索引时,数据库需要扫描整个表(全表扫描)。
-
有索引时,数据库只需扫描索引结构,快速定位目标数据。
-
-
高效的数据结构:
-
索引通常使用 B+树等高效数据结构,支持快速查找、插入和删除操作。
-
B+树的时间复杂度为 O(log n),远低于全表扫描的 O(n)。
-
-
排序和范围查询优化:
-
索引对数据进行了排序,支持高效的等值查询和范围查询。
-
例如,查询
WHERE age BETWEEN 20 AND 30
时,索引可以快速定位到范围内的数据。
-
-
减少磁盘 I/O:
-
索引通常比表数据小,可以加载到内存中,减少磁盘 I/O 操作。
-
无索引时,数据库可能需要多次读取磁盘来扫描整个表。
-
二、事务数据字典
事务数据字典是数据库管理系统(DBMS)中用于存储和管理元数据(Metadata)的系统表或数据结构。元数据是描述数据库对象(如表、索引、列、约束等)的信息。事务数据字典确保这些元数据在事务处理过程中保持一致性和完整性。
事务数据字典的主要功能
-
存储元数据:保存数据库对象的定义和结构信息。
-
支持事务:确保元数据操作(如创建、修改、删除表)具有事务性,要么全部成功,要么全部回滚。(原子性)
-
一致性维护:保证元数据与数据的一致性。
-
权限管理:存储用户权限和角色信息,支持权限管理。
事务数据字典的常见内容
-
表信息:表名、列名、数据类型、约束等。
-
索引信息:索引名、索引类型、索引列等。
-
视图信息:视图定义、依赖的表和列等。
-
约束信息:主键、外键、唯一约束、检查约束等。
-
用户和权限:用户账号、角色、权限分配等。
-
存储信息:表空间、文件路径、存储参数等。
事务数据字典的实现
不同数据库管理系统有各自的实现方式,常见的有:
-
系统表:如 MySQL 的
information_schema
和mysql
数据库。 -
数据字典表:如 Oracle 的
DBA_*
、ALL_*
、USER_*
视图。 -
内存结构:部分数据库将数据字典信息加载到内存以提高访问速度。
示例:MySQL 中的事务数据字典
MySQL 8.0 引入了事务性数据字典,将元数据存储在 InnoDB 表中,确保元数据操作具有事务性。
-
查看表信息:
SELECT * FROM information_schema.TABLES WHERE table_schema = 'your_database_name';
-
查看列信息:
SELECT * FROM information_schema.COLUMNS WHERE table_schema = 'your_database_name' AND table_name = 'your_table_name';
-
查看索引信息:
SELECT * FROM information_schema.STATISTICS WHERE table_schema = 'your_database_name' AND table_name = 'your_table_name';
示例:Oracle 中的事务数据字典
Oracle 使用数据字典视图来管理元数据。
-
查看表信息:
SELECT * FROM DBA_TABLES WHERE owner = 'YOUR_SCHEMA';
-
查看列信息:
SELECT * FROM DBA_TAB_COLUMNS WHERE owner = 'YOUR_SCHEMA' AND table_name = 'YOUR_TABLE';
-
查看索引信息:
SELECT * FROM DBA_INDEXES WHERE owner = 'YOUR_SCHEMA' AND table_name = 'YOUR_TABLE';
事务数据字典的优势
-
事务性:确保元数据操作具有原子性、一致性、隔离性和持久性(ACID)。
-
一致性:保证元数据与数据的一致性。
-
安全性:通过权限管理保护元数据。
三、元数据
元数据是有关存储在RDBMS中的数据的信息,如列定义、索引定义、约束等。
数据字典是RDBMS中所有的数据的元数据集中资料档案库。
四、单表文件表空间和通用表空间
在 MySQL 中,表空间(Tablespace)是用于存储表数据和索引的物理文件。MySQL 支持多种表空间类型,其中 单表文件表空间 和 通用表空间 是两种常见的表空间管理方式。它们的主要区别在于如何组织和管理表的存储。
1. 单表文件表空间(File-Per-Table Tablespace)
单表文件表空间是 MySQL 的默认表空间类型(InnoDB 存储引擎)。每个表都有一个独立的 .ibd
文件来存储表的数据和索引。
特点:
-
每个表一个文件:每个表的数据和索引存储在一个独立的
.ibd
文件中。 -
文件位置:默认情况下,
.ibd
文件位于数据库目录下(如/var/lib/mysql/database_name/
)。 -
灵活性:可以单独管理每个表的文件,例如移动、备份或删除。
-
空间回收:删除表时,对应的
.ibd
文件会被删除,空间会立即释放。
启用方式:
单表文件表空间是 MySQL 5.6 及以上版本的默认行为。可以通过以下配置确认:
SHOW VARIABLES LIKE 'innodb_file_per_table';
如果值为 ON
,则表示启用单表文件表空间。
优点:
-
独立性:每个表的文件独立,便于管理和维护。
-
空间回收:删除表时,空间会立即释放。
-
备份灵活:可以单独备份或恢复某个表。
缺点:
-
文件数量多:如果表数量很多,会导致文件数量过多,可能影响文件系统的性能。
-
空间浪费:每个表都有自己的文件,可能导致一定的空间浪费(如文件系统的最小分配单元)。
示例:
创建一个使用单表文件表空间的表:
CREATE TABLE example_table ( id INT PRIMARY KEY, name VARCHAR(100) ) ENGINE=InnoDB;
对应的 .ibd
文件会存储在数据库目录下,如:
/var/lib/mysql/database_name/example_table.ibd
2. 通用表空间(General Tablespace)
通用表空间是 MySQL 5.7 引入的一种表空间类型。它允许将多个表的数据和索引存储在同一个表空间文件中。
特点:
-
共享文件:多个表可以共享同一个表空间文件。
-
文件位置:通用表空间文件可以存储在任意位置,由用户指定。
-
灵活性:可以将多个表的数据集中存储,减少文件数量。
-
空间管理:删除表时,空间不会立即释放,而是可以供其他表复用。
创建通用表空间:
CREATE TABLESPACE general_ts ADD DATAFILE 'general_ts.ibd' ENGINE=InnoDB;
将表添加到通用表空间:
CREATE TABLE example_table ( id INT PRIMARY KEY, name VARCHAR(100) ) TABLESPACE general_ts;
优点:
-
减少文件数量:多个表共享一个表空间文件,减少文件系统压力。
-
集中管理:可以集中管理多个表的存储。
-
灵活存储:表空间文件可以存储在任意位置。
缺点:
-
空间回收:删除表时,空间不会立即释放,而是保留在表空间文件中。
-
管理复杂:需要手动管理表空间文件。
示例:
-
创建通用表空间:
CREATE TABLESPACE general_ts ADD DATAFILE '/path/to/general_ts.ibd' ENGINE=InnoDB;
-
创建表并指定通用表空间:
CREATE TABLE example_table ( id INT PRIMARY KEY, name VARCHAR(100) TABLESPACE general_ts;
-
查看表空间信息:
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES;
单表文件表空间 vs 通用表空间
特性 | 单表文件表空间 | 通用表空间 |
---|---|---|
文件数量 | 每个表一个文件 | 多个表共享一个文件 |
空间回收 | 删除表时立即释放空间 | 删除表时空间不立即释放 |
管理灵活性 | 每个表独立管理 | 集中管理多个表 |
文件位置 | 默认在数据库目录下 | 可指定任意位置 |
适用场景 | 表数量较少,需要独立管理的场景 | 表数量较多,需要集中管理的场景 |
五、MVCC
MVCC(多版本并发控制)是一种用于数据库管理系统的并发控制机制,旨在提高数据库的并发性能,同时避免读写冲突。MVCC通过维护数据的多个版本来实现非阻塞的读操作,从而允许多个事务并发执行不会相互阻塞。
MVCC 的核心思想
MVCC 的核心思想是为每个事务提供数据的“快照”(Snapshot),使得每个事务在读取数据时看到的是事务开始时的数据状态,而不受其他并发事务的影响。这样,读操作不会阻塞写操作,写操作也不会阻塞读操作,从而提高了并发性能。
MVCC 的工作原理
-
版本链:每行数据可能有多个版本,每个版本包含一个时间戳或事务 ID,用于标识该版本的创建时间和有效时间。
-
读操作:事务读取数据时,系统会根据事务的开始时间或事务 ID 选择合适的版本,确保事务看到一致的数据视图。
-
写操作:事务修改数据时,系统会创建数据的新版本,而不是直接覆盖旧版本。旧版本仍然保留,供其他事务读取。
-
垃圾回收:当某个数据版本不再被任何事务需要时,系统会将其标记为可回收,并在适当的时候进行清理。
MVCC 的优点
-
高并发:读操作不会阻塞写操作,写操作也不会阻塞读操作,从而提高了数据库的并发性能。
-
一致性:每个事务看到的数据视图是一致的,避免了脏读、不可重复读和幻读等问题。
-
非阻塞:读操作不需要加锁,减少了锁争用和死锁的可能性。
MVCC 的缺点
-
存储开销:需要维护数据的多个版本,增加了存储空间的开销。
-
垃圾回收:需要定期清理不再使用的数据版本,增加了系统的复杂性。
-
写冲突:虽然读操作不会阻塞写操作,但写操作之间仍然可能发生冲突,需要进行冲突检测和解决。
MVCC 的实现
不同的数据库管理系统对 MVCC 的实现方式有所不同。以下是一些常见的实现方式:
-
MySQL(InnoDB):
-
使用回滚段(Undo Log)来存储数据的历史版本。
-
每个事务在修改数据时,会创建一个新的版本,并将旧版本存储在回滚段中。
-
通过事务 ID 和回滚指针(Rollback Pointer)来管理数据版本。
-
示例:MYSQL 中的 MVCC
假设有一个表 accounts
,包含以下数据:
id | name | balance | xmin | xmax |
---|---|---|---|---|
1 | Alice | 100 | 100 | NULL |
2 | Bob | 200 | 101 | NULL |
-
事务 A(XID=102)开始并读取
accounts
表,看到的数据是:SELECT * FROM accounts;
结果:
id name balance 1 Alice 100 2 Bob 200 -
事务 B(XID=103)开始并更新
accounts
表,将 Alice 的余额改为 150:UPDATE accounts SET balance = 150 WHERE id = 1;
更新后,
accounts
表的数据变为:id name balance xmin xmax 1 Alice 100 100 103 1 Alice 150 103 NULL 2 Bob 200 101 NULL -
事务 A 再次读取
accounts
表,仍然看到旧的数据:SELECT * FROM accounts;
结果:
id name balance 1 Alice 100 2 Bob 200 -
事务 B 提交后,事务 A 再次读取
accounts
表,仍然看到旧的数据,因为事务 A 看到的是事务开始时的数据快照。
那为什么事务B提交后A看的还是100,那什么时候能看到150呢?
这个问题和MVCC的事务隔离级别有关,在Repeatable Read级别下,事务在整个执行过程中看到的数据是一致的,不受其他事务提交的影响。
而在Read Committed隔离级别下,事务可以看到其他事务提交后的最新数据。
六、重做日志和还原日志
作用:确保数据的一致性和事务的完整性
主要作用如下:
1. 重做日志(Redo Log)
- 作用:重做日志用于记录对数据库的所有修改操作(如插入、更新、删除),以便在系统崩溃或故障后能够重新应用这些操作,恢复数据库到故障前的状态。
- 工作原理:
- 当事务提交时,系统会先将修改操作写入重做日志,然后再将数据写入磁盘。
- 如果系统崩溃,恢复过程会读取重做日志,重新执行其中的操作,确保已提交的事务被持久化。
- 特点:
- 重做日志是顺序写入的,性能较高。
- 主要用于保证数据的持久性(Durability)。
- 应用场景:系统崩溃后的恢复、数据备份的恢复等。
2. 还原日志(Undo Log)
- 作用:还原日志用于记录事务执行前的数据状态,以便在事务回滚或系统需要撤销某些操作时,能够将数据恢复到事务开始前的状态。
- 工作原理:
- 当事务执行修改操作时,系统会先将修改前的数据状态记录到还原日志中。
- 如果事务需要回滚,系统会根据还原日志将数据恢复到事务开始前的状态。
- 特点:
- 还原日志主要用于保证事务的原子性(Atomicity)和一致性(Consistency)。
- 支持事务的回滚操作。
- 应用场景:事务回滚、并发控制中的一致性维护等。
3. 重做日志与还原日志的区别
表格
特性 | 重做日志(Redo Log) | 还原日志(Undo Log) |
---|---|---|
目的 | 确保已提交事务的持久化 | 支持事务回滚和一致性恢复 |
记录内容 | 修改后的数据状态 | 修改前的数据状态 |
使用场景 | 系统崩溃后的恢复 | 事务回滚、并发控制 |
与事务的关系 | 记录已提交事务的修改 | 记录未提交事务的修改 |
持久性 | 必须持久化到磁盘 | 通常也持久化,但可能被清理 |
4. 协同工作
- 在事务处理中,重做日志和还原日志通常会协同工作:
- 当事务提交时,重做日志确保修改被持久化。
- 当事务回滚时,还原日志确保数据恢复到事务开始前的状态。
- 在系统恢复过程中,重做日志用于重新应用已提交的事务,而还原日志用于撤销未提交的事务。
5. 实际应用
- 数据库恢复:在数据库崩溃后,系统会先使用还原日志回滚未提交的事务,然后使用重做日志重新应用已提交的事务。
- 事务管理:在并发事务中,还原日志用于实现多版本并发控制(MVCC),确保事务的隔离性。