讲解

MySQL 的一个独特设计是「可插拔存储引擎」:Server 层负责连接、解析、优化,真正存取数据的是引擎层,建表时用 ENGINE= 指定。今天的答案几乎总是 InnoDB——它支持事务、行级锁、MVCC(多版本并发控制,读写不互相阻塞)、外键,并且崩溃后能靠 redo log 自动恢复。MySQL 8.0 起连系统表都全部换成了 InnoDB,它是毫无争议的默认选择。

MyISAM 是上古引擎,只支持表级锁、不支持事务和外键,崩溃后容易损坏需要修复。它的历史优势(全文索引、表空间小)早已被 InnoDB 追平,现在还新建 MyISAM 表的唯一理由是维护遗留系统。SHOW ENGINES 可以列出服务器支持的所有引擎,其中 PERFORMANCE_SCHEMA、MEMORY、CSV 等各有专用场景,但业务表认准 InnoDB。

InnoDB 还有两个管理视角要知道:一是行格式,默认 DYNAMIC,决定了变长列和大字段的存储方式,一般不用动;二是表空间,默认 innodb_file_per_table=ON 时每张表一个 .ibd 文件,删表能真正释放磁盘——如果关掉这个选项,所有表挤在共享表空间里,删表后文件也不会缩小。

示例

查看服务器支持的引擎和当前默认引擎(Support 列的 DEFAULT 即默认引擎):

SHOW ENGINES;

SELECT @@GLOBAL.default_storage_engine AS default_engine;

建两张结构相同、引擎不同的表,从元数据对比它们的引擎与行格式:

CREATE TABLE innodb_demo (id INT PRIMARY KEY, note VARCHAR(50)) ENGINE=InnoDB;

CREATE TABLE myisam_demo (id INT PRIMARY KEY, note VARCHAR(50)) ENGINE=MyISAM;

SELECT TABLE_NAME, ENGINE, ROW_FORMAT, CREATE_OPTIONS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
ORDER BY TABLE_NAME;

常见坑

  • 新建表还在用 MyISAM:任何新表都没有理由不用 InnoDB。接手老系统时先查 SELECT TABLE_NAME FROM information_schema.TABLES WHERE ENGINE = 'MyISAM',规划迁移。
  • 以为引擎是库级设置:引擎是每张表的属性,同一个库可以混用。但混用后跨引擎的「事务」只保护 InnoDB 部分,MyISAM 的修改不会回滚,极易造成不一致。
  • 事务里混了 MyISAM 还以为安全:START TRANSACTION 对 MyISAM 表完全无效,UPDATE 立即生效,ROLLBACK 救不回来。
  • 误解存储过程的事务边界:这是引擎话题的延伸——原子性来自 InnoDB,不来自你写了 BEGIN。

小结

业务表一律 InnoDB:事务、行锁、MVCC、崩溃恢复都靠它;MyISAM 只存在于遗留系统。下一章解决中文环境最高频的事故源头:字符集。