乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

存储引擎对比

导学

CREATE TABLE 时写的 ENGINE=InnoDB 不是摆设——它决定了这张表的数据怎么存、支不支持事务、崩溃后能不能恢复。MySQL 5.7 支持多种存储引擎,但生产环境 99% 的场景只需要 InnoDB。理解各引擎的核心差异,才能在特定场景(如只读归档、临时缓存)做出正确选择,而不是盲目跟风或固守单一方案。

定义

存储引擎(Storage Engine):MySQL 中负责数据存储、索引管理、事务支持、并发控制等底层操作的插件式组件。不同引擎在磁盘格式、内存结构、锁机制、事务支持上完全不同,对同一张表执行 SELECT/INSERT,底层可能走完全不同的代码路径。

核心引擎对比

特性InnoDBMyISAMMEMORYARCHIVE
事务✅ 支持(ACID)❌ 不支持❌ 不支持❌ 不支持
行级锁✅ 支持❌ 表级锁❌ 表级锁❌ 行级锁(插入时)
崩溃恢复✅ redo log + undo log❌ 需修复工具❌ 数据丢失❌ 数据可能损坏
外键✅ 支持❌ 不支持❌ 不支持❌ 不支持
全文索引✅ 5.6.4+ 支持✅ 原生支持❌ 不支持❌ 不支持
数据缓存缓冲池(数据和索引)只缓存索引全部在内存无缓存
存储格式表空间文件(.ibd)数据(.MYD) + 索引(.MYI)内存中高压缩归档文件
适用场景通用 OLTP只读/全文检索/日志分析临时表/会话缓存审计日志/历史归档
MySQL 5.7 默认✅ 默认引擎❌ 非默认❌ 非默认❌ 非默认

SQL 示例

场景一:查看支持的存储引擎

执行语句:

SHOW ENGINES;

操作后结果(MySQL 5.7 典型输出):

EngineSupportCommentTransactionsXASavepoints
InnoDBDEFAULTSupports transactions, row-level locking, and foreign keysYESYESYES
MyISAMYESMyISAM storage engineNONONO
MEMORYYESHash based, stored in memory, useful for temporary tablesNONONO
ARCHIVEYESArchive storage engineNONONO
BLACKHOLEYES/dev/null storage engine (anything you write to it disappears)NONONO
CSVYESCSV storage engineNONONO
FEDERATEDNOFederated MySQL storage engineNULLNULLNULL
MRG_MYISAMYESCollection of identical MyISAM tablesNONONO
PERFORMANCE_SCHEMAYESPerformance SchemaNONONO

结果解读:

  • Support = DEFAULT:InnoDB 是 5.7 的默认存储引擎
  • Support = YES:可用但未默认;NO:未启用或不可用
  • Transactions = YES:只有 InnoDB 支持事务,其他引擎的 DML 都是自动提交的
  • XA = YES:只有 InnoDB 支持 XA 分布式事务

场景二:创建不同引擎的表并观察差异

执行语句:

-- InnoDB 表(默认,支持事务和行锁)
CREATE TABLE employees_innodb (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
) ENGINE=InnoDB;

-- MyISAM 表(表锁,不支持事务)
CREATE TABLE employees_myisam (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
) ENGINE=MyISAM;

-- MEMORY 表(数据存内存,重启丢失)
CREATE TABLE employees_memory (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
) ENGINE=MEMORY;

-- 插入相同数据
INSERT INTO employees_innodb (emp_name, dept, score) VALUES ('大翔', '技术部', 100);
INSERT INTO employees_myisam (emp_name, dept, score) VALUES ('大翔', '技术部', 100);
INSERT INTO employees_memory (emp_name, dept, score) VALUES ('大翔', '技术部', 100);

查看表文件(Linux 数据目录下):

# InnoDB: 数据在共享表空间或独立 .ibd 文件
ls employees_innodb*
# employees_innodb.frm  employees_innodb.ibd

# MyISAM: 数据和索引分开存储
ls employees_myisam*
# employees_myisam.frm  employees_myisam.MYD  employees_myisam.MYI

# MEMORY: 只有表结构定义文件,无数据文件
ls employees_memory*
# employees_memory.frm

结果解读:

  • InnoDB:.frm(表结构)+ .ibd(数据和索引,如果 innodb_file_per_table=ON)
  • MyISAM:.frm(表结构)+ .MYD(数据文件)+ .MYI(索引文件)。数据和索引分离,可以单独压缩数据或修复索引
  • MEMORY:只有 .frm 文件,所有数据存在内存中,MySQL 重启后数据全部丢失

场景三:事务支持差异(InnoDB vs MyISAM)

当前数据状态:employees_innodb 和 employees_myisam 各有 1 条数据。

执行语句:

-- ========== InnoDB:支持事务回滚 ==========
START TRANSACTION;
INSERT INTO employees_innodb (emp_name, dept, score) VALUES ('白歌', '技术部', NULL);
ROLLBACK;

SELECT * FROM employees_innodb;

InnoDB 操作后结果:

emp_idemp_namedeptscore
1大翔技术部100
-- ========== MyISAM:不支持事务,ROLLBACK 无效 ==========
-- MyISAM 没有 START TRANSACTION 语义,每条语句自动提交
INSERT INTO employees_myisam (emp_name, dept, score) VALUES ('白歌', '技术部', NULL);

-- 尝试"回滚"(MyISAM 没有事务,这条语句只是空操作)
ROLLBACK;

SELECT * FROM employees_myisam;

MyISAM 操作后结果:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

结果解读:

  • InnoDB 的 ROLLBACK 成功撤销了未提交的插入,数据保持 1 条
  • MyISAM 没有事务概念,INSERT 立即持久化,ROLLBACK 对其无效,数据变成 2 条
  • 这是选择引擎的首要原则:需要事务一致性(转账、订单)必须用 InnoDB

场景四:MEMORY 引擎的数据易失性

当前数据状态:employees_memory 有 1 条数据。

执行语句:

-- 查看 MEMORY 表数据
SELECT * FROM employees_memory;

操作后结果:

emp_idemp_namedeptscore
1大翔技术部100
-- 模拟重启后(实际执行 FLUSH TABLES 或重启 MySQL 服务)
-- 数据全部丢失,只剩空表结构
SELECT * FROM employees_memory;

重启后结果:

Empty set (0.00 sec)

结果解读:

  • MEMORY 引擎所有数据保存在内存中,查询速度极快(类似 Redis)
  • 但MySQL 重启、崩溃、甚至 FLUSH TABLES 都可能导致数据丢失
  • 适用场景:临时计算结果、会话级缓存、中间计算表。不适合持久化存储
  • MEMORY 表默认使用哈希索引,等值查询极快,但范围查询和排序性能差

场景五:ARCHIVE 引擎的高压缩存储

执行语句:

-- 创建 ARCHIVE 表(高压缩,只支持 INSERT 和 SELECT)
CREATE TABLE logs_archive (
    log_id INT PRIMARY KEY AUTO_INCREMENT,
    message VARCHAR(500),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=ARCHIVE;

-- ARCHIVE 支持插入
INSERT INTO logs_archive (message) VALUES
('用户登录成功'),
('订单创建: #1001'),
('支付完成: #1001');

SELECT * FROM logs_archive;

操作后结果:

log_idmessagecreated_at
1用户登录成功2024-01-15 10:00:00
2订单创建: #10012024-01-15 10:00:01
3支付完成: #10012024-01-15 10:00:02
-- ARCHIVE 不支持 UPDATE/DELETE/索引(主键也是逻辑上的,无实际索引)
UPDATE logs_archive SET message = '修改' WHERE log_id = 1;
-- ERROR 1031 (HY000): Table storage engine for 'logs_archive' doesn't have this option

结果解读:

  • ARCHIVE 引擎使用 zlib 压缩,存储空间通常只有 InnoDB 的 1/5 ~ 1/10
  • 只支持 INSERT 和 SELECT,不支持 UPDATE、DELETE、索引、事务
  • 插入时会被压缩,查询时实时解压,所以查询比 InnoDB 慢
  • 适用场景:审计日志、操作记录、历史归档——写入后不再修改,但需要长期保留备查

常见误区

误区正解
"MyISAM 比 InnoDB 快,所以应该用 MyISAM"不是。MyISAM 在读密集、无并发的场景可能更快,但表锁导致并发写入性能极差,且不支持事务和崩溃恢复。5.7 及以后版本 InnoDB 在绝大多数场景都更优。
"MEMORY 引擎适合做缓存替代 Redis"不推荐。MEMORY 表受 MySQL 内存限制、无持久化、重启丢失、不支持复杂数据类型。专业缓存用 Redis/Memcached。
"ARCHIVE 可以替代 InnoDB 存日志"不完全。ARCHIVE 压缩率高但查询慢、不支持索引和 UPDATE。如果日志需要频繁查询或修改状态,InnoDB 更合适。
"存储引擎可以在表级别混用,所以一个库可以用多种引擎"技术上可以,但不推荐。跨引擎的事务无法保证一致性(如 InnoDB 表和 MyISAM 表在同一个事务中,MyISAM 的部分无法回滚)。
"BLACKHOLE 引擎没用"有特定用途。BLACKHOLE 不存储任何数据,只记录 binlog,适合作为中继从库(relay slave)减少存储开销,或测试 binlog 复制性能。
"CSV 引擎可以方便地导出数据"不是。CSV 引擎确实以 CSV 格式存储,但性能差、不支持索引和事务。数据导出用 SELECT ... INTO OUTFILE 更专业。

面试考点

Q:InnoDB 和 MyISAM 的核心区别?

  1. 事务:InnoDB 支持 ACID 事务,MyISAM 不支持;2. 锁:InnoDB 行级锁,MyISAM 表级锁;3. 崩溃恢复:InnoDB 有 redo/undo log,崩溃后可恢复,MyISAM 可能损坏需修复;4. 外键:InnoDB 支持,MyISAM 不支持;5. 存储:InnoDB 聚簇索引(数据和主键在一起),MyISAM 非聚簇(数据和索引分离);6. 全文索引:MyISAM 原生支持,InnoDB 5.6.4+ 支持。MySQL 5.7 默认和推荐都是 InnoDB。

Q:什么场景还会用 MyISAM?

极少数场景:1. 纯只读且需要全文检索的老系统(5.6 之前 InnoDB 不支持全文索引);2. 需要极度压缩的静态数据(MyISAM 支持 myisampack 压缩);3. 某些 GIS 空间数据的旧应用。新项目不应使用 MyISAM。

Q:MEMORY 引擎的索引类型?

MEMORY 引擎默认使用哈希索引(HASH),等值查询(=、IN)极快,但范围查询(>、<、BETWEEN)和排序必须全表扫描。建表时可以指定 INDEX idx USING BTREE 改用 B-Tree 索引,支持范围查询。

Q:跨存储引擎的事务有什么问题?

如果事务中同时操作 InnoDB 表和 MyISAM 表,InnoDB 部分可以正常回滚,但 MyISAM 部分的变更已经自动提交,无法回滚。这会导致数据不一致。一个事务内的所有表应使用同一引擎,且需要事务支持时必须全部用 InnoDB。

Q:如何查看和修改表的存储引擎?

查看:SHOW CREATE TABLE table_name; 或 SHOW TABLE STATUS LIKE 'table_name';。修改:ALTER TABLE table_name ENGINE=InnoDB;。注意:修改引擎会重建整张表,大表需要维护窗口或使用 pt-online-schema-change。

小结

  • InnoDB:MySQL 5.7 默认引擎,支持事务、行锁、崩溃恢复、外键,适合 99% 的 OLTP 场景
  • MyISAM:表锁、无事务、数据和索引分离,只读/全文检索老系统可能用到,新项目不推荐
  • MEMORY:数据存内存,查询极快但重启丢失,适合临时表和会话缓存
  • ARCHIVE:高压缩、只支持 INSERT/SELECT,适合审计日志和历史归档
  • 生产环境优先统一使用 InnoDB,跨引擎事务会导致不一致

下一章引子:存储引擎决定了表的"性格",而 InnoDB 作为最复杂的引擎,内部还有 Change Buffer 和 Doublewrite Buffer 等机制来平衡性能与可靠性——它们是 InnoDB 既能高速写入又能保证数据不损坏的秘密武器。

上一页
复合索引
下一页
分区表