--- tags: [MySQL, MyISAM, Memory, Archive, 存储引擎] create time: 2026-05-16 00:00 --- # MyISAM / Memory / Archive 引擎概览 ## 概述 虽然生产环境几乎全部使用 InnoDB,但了解其他存储引擎的特点对于特定场景决策和理解 MySQL 历史演进仍然有价值。 ## MyISAM MyISAM 是 MySQL 4.x 时代的默认引擎,在 5.5 版本之后被 InnoDB 取代。 ```mermaid flowchart TB subgraph FS["MyISAM 文件结构"] MYD[".MYD — 数据文件"] MYI[".MYI — 索引文件"] FRM[".FRM — 表结构文件"] end subgraph FEAT["核心特性"] T1["❌ 不支持事务"] T2["❌ 不支持外键"] T3["❌ 只有表锁
无行锁"] T4["✅ 压缩存储
(myisampack)"] T5["✅ 全文索引
(8.0 前唯一选择)"] T6["✅ 读密集型场景较快"] end style FS fill:#F8EFBA,color:#000 style FEAT fill:#D0E8FD,color:#000 ``` > [!QUOTE] 思考一下 > MyISAM 将数据和索引分存为两个独立文件。这种设计看似简洁,但正是**缺乏事务支持(InnoDB 的 Redo Log + Undo Log)**和**行级锁**的根本原因——没有机制保证原子性和并发安全。 ### MyISAM 的表锁机制 ```mermaid sequenceDiagram participant C1 as Client A (WRITE) participant S as Server participant C2 as Client B (READ) C1->>S: LOCK TABLES users WRITE S->>S: 获取表级写锁 C1->>S: INSERT INTO users ... C1->>S: UPDATE users SET ... C1->>S: UNLOCK TABLES C2->>S: SELECT * FROM users Note over S: ⚠️ 阻塞!等待写锁释放 S-->>C2: (等待中...) C1->>S: UNLOCK TABLES S-->>C2: 返回结果集 ``` > [!WARNING] 表锁的危害 > MyISAM 的表锁意味着**一个写操作会阻塞所有其他操作**(包括读)。在并发场景中这是灾难性的——即使是纯 SELECT 也会被阻塞。这就是为什么现代项目不应该再用 MyISAM。 ### MyISAM 还能用在什么地方? 极少数场景: - **静态只读日志**:导入一次、长期查询、绝不更新 - **GIS 数据**:MyISAM 的 spatial index 在某些老版本上更快 - **遗留迁移**:老旧系统的临时兼容层 > [!CAUTION] MyISAM 全文索引已过时 > MySQL 5.6+ 起 InnoDB 已支持 FULLTEXT 索引,8.0 后更是全面强化。MyISAM 作为"唯一全文索引选择"的优势已基本消失。 **结论:新项目不用 MyISAM。** > [!TIP] 面试高频考点 > 面试官问"MyISAM vs InnoDB"时,核心差异就是三点:**锁粒度、事务、外键**。只要答出这三点,基本就拿满分了。 ## Memory(HEAP)引擎 Memory 引擎将所有数据存储在内存中,表结构存在于磁盘 `.frm` 文件中。 ```mermaid flowchart TD A["CREATE TABLE ... ENGINE=MEMORY"] --> B["数据全在内存"] B --> C["极速读写 O(1)"] B --> D["重启后数据丢失 ⚠️"] C --> E["适合场景"] E --> E1["临时聚合计算结果"] E --> E2["字典表缓存"] E --> E3["会话级临时查找表"] style B fill:#EE5A24,color:#fff style E3 fill:#00D866,color:#fff ``` ```sql -- Memory 引擎使用示例 CREATE TABLE session_lookup ( session_id CHAR(32) PRIMARY KEY, user_id BIGINT, last_access TIMESTAMP, payload JSON ) ENGINE=Memory; -- ⚠️ 注意限制 -- 1. VARCHAR/TEXT/BLOB 会使用 MEMORY 的内部映射转为固定长度 -- 2. 不支持 AUTO_INCREMENT -- 3. 受 max_heap_table_size 和 tmp_table_size 限制 -- 4. 表在 MySQL 重启或 flush tables 时消失 -- 5. HASH 索引是默认值,BRIN 索引可通过 explicit index type 指定(MySQL 8.0+) -- 💡 调优:调整上限 SET SESSION max_heap_table_size = 512 * 1024 * 1024; -- 512MB SET GLOBAL tmp_table_size = 512 * 1024 * 1024; ``` > [!NOTE] Memory vs Redis > 很多人问"能不能用 Memory 引擎代替 Redis 做缓存"。答案是:通常不建议。 > - Redis 有更丰富的数据结构(Sorted Set、Bitmap、Stream) > - Redis 支持持久化和集群 > - Redis 有成熟的驱动和生态 > - MySQL Memory 引擎在连接断开时也会丢数据 ## Archive 引擎 Archive 引擎专为"存而不查"的场景设计,采用行级锁 + 压缩存储。 ```mermaid flowchart LR A["INSERT 数据"] --> B["Row-level compression
每行独立压缩"] B --> C["仅支持 SELECT / INSERT"] C --> D["❌ 不支持 DELETE"] C --> E["❌ 不支持 UPDATE"] C --> F["❌ 不使用索引"] style C fill:#FF9F43,color:#000 ``` ### 适用场景 | 场景 | 说明 | |------|------| | 日志归档 | 系统日志、审计日志只写不读 | | 数据仓库 ETL | 海量事实表的增量导入 | | 统计报表底表 | 定期导入后供离线分析 | ```sql -- Archive 引擎示例 CREATE TABLE audit_log ( id BIGINT AUTO_INCREMENT, -- Archive 允许自增但不作索引查找用 created_at DATETIME DEFAULT CURRENT_TIMESTAMP, action VARCHAR(50), details TEXT, PRIMARY KEY (id) -- 仅用于自增,不参与查找 ) ENGINE=Archive; -- ⚠️ MySQL 8.0+ 不再需要 ROW_FORMAT=COMPRESSED -- Archive 引擎默认就是压缩存储,显式指定会报语法错误 -- 典型用法:按月分区归档 ALTER TABLE audit_log PARTITION BY RANGE (YEAR(created_at)) ( PARTITION p2025 VALUES LESS THAN (2026), PARTITION p2026 VALUES LESS THAN (2027) ); ``` > [!NOTE] 为什么 Archive 不支持 UPDATE / DELETE? > Archive 的行是**连续压缩存储**的——每一行都依赖于前一行解压后的位置。如果随机修改或删除中间某行,整个压缩链就要重新计算,这在设计上是不可接受的。所以它干脆禁止了这些操作,只保留 INSERT + SELECT。 ## 引擎切换指南 ### 如何查看当前支持的引擎? ```sql SHOW ENGINES; -- 关注 Support 列:YES(默认)、DEFAULT、NO(不支持) ``` ### 如何修改引擎? ```sql -- 创建新表时指定 CREATE TABLE archive_data (...) ENGINE=Archive; -- 已存在表的转换(在线执行可能需要较长时间) ALTER TABLE old_table ENGINE=InnoDB; -- ⚠️ ALTER TABLE 原理 -- 1. 创建临时表(新引擎) -- 2. 逐行拷贝旧表数据到新表 -- 3. 加排他锁,替换文件名 -- 4. 删除旧表 -- 大表转换会占用双倍空间和锁定时间 ``` ### 为什么生产环境几乎只用 InnoDB ```mermaid flowchart TD Check{"需要事务?"} Check -->|是| INNODB["✅ InnoDB"] Check -->|否| Q2{"高读低写?"} Q2 -->|是| MEM{"✅ Memory(缓存)
或 MyISAM(静态)"} Q2 -->|否| ARCH{"纯追加场景?"} ARCH -->|是| ARC["✅ Archive"] ARCH -->|否| INNODB style INNODB fill:#00D866,color:#fff style MEM fill:#FF9F43,color:#000 style ARC fill:#C44569,color:#fff ``` > [!TIP] 决策原则 > 记住一句话:**"默认 InnoDB,特殊情况再考虑其他"**。InnoDB 是 MySQL 设计者的首选推荐,只有在性能极端优化或有特殊需求时,才值得切换引擎。 ## 关联笔记 - [[hhs/MySQL/04-存储引擎/19-InnoDB 深度解析]] — InnoDB 五大核心组件完整文档 - [[hhs/GORM/13-多数据库支持]] — GORM 在不同数据库间的移植注意事项