MySQL 5.5+ 版本預設且強烈推薦使用 InnoDB。 MyISAM 僅適用於極少數唯讀、全文搜尋(5.6 前)、空間索引等特殊場景。理解兩者差異,是效能調優與架構設計的基石。
| 維度 | MyISAM | InnoDB | 影響 |
|---|---|---|---|
| 事務支援 | ❌ 不支援 | ✅ 完整 ACID | 金融、訂單等核心業務必須 InnoDB |
| 外鍵約束 | ❌ | ✅ | 資料完整性保障 |
| 鎖粒度 | 表級鎖 | 行級鎖 | 高並發寫入 InnoDB 完勝 |
| MVCC | ❌ | ✅ | 讀寫不阻塞,並發效能核心 |
| 崩潰恢復 | ❌ 需人工修復 | ✅ Redo/Undo Log 自動恢復 | 生產環境可靠性分水嶺 |
| 叢集索引 | ❌ 堆表 | ✅ 主鍵叢集索引 | 主鍵查詢極快,二級索引需回表 |
| 全文索引 | ✅ (5.6 前唯一) | ✅ (5.6+) | 5.6+ 兩者皆支援 |
| 空間索引 | ✅ | ✅ (5.7+) | GIS 應用考量 |
| 壓縮表 | ✅ myisampack | ✅ 行壓縮/頁壓縮 | InnoDB 壓縮更靈活 |
| 儲存空間 | 較小 | 較大(約 2-3 倍) | 空間敏感場景權衡 |
| COUNT(*) | O(1) 直接讀取計數器 | O(N) 掃描 | InnoDB 需配合觸發器/快取優化 |
-- Session A BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- 鎖住 id=1 這一行 -- Session B (並發執行) SELECT * FROM accounts WHERE id = 2; -- 完全不受阻塞,讀取 id=2 UPDATE accounts SET balance = balance + 100 WHERE id = 2; -- 鎖住 id=2,互不干擾
MyISAM 表級鎖會導致 Session B 完全阻塞,並發效能呈指數級下降。
innodb_flush_log_at_trx_commit = 1 時,事務提交強制 Redo Log 刷盤,崩潰零數據丟失。配合 Doublewrite Buffer 防止半寫頁。
ALTER TABLE tbl_name ENGINE=InnoDB; -- 注意事項: -- 1. 鎖表時間與資料量成正比,大表建議 pt-online-schema-change -- 2. 主鍵必須存在(無主鍵 InnoDB 會隱式生成 6 字節 row_id) -- 3. 全文索引需重建 (5.6+) -- 4. 空間索引需重建 (5.7+) -- 5. 記憶體配置調整:key_buffer_size ↓, innodb_buffer_pool_size ↑
| 引擎 | 定位 | 殺手級特性 |
|---|---|---|
| Memory | 臨時表/快取 | 純記憶體、極速、重啟丟失 |
| Archive | 日誌歸檔 | 高壓縮比、僅支援 INSERT/SELECT |
| TokuDB | 大數據寫入/壓縮 | 分形樹索引、壓縮比 10x、寫入極快 |
| ColumnStore | OLAP/數據倉庫 | 列式儲存、向量化執行、聚合查詢極快 |
| RocksDB/MyRocks | 高寫入/空間敏感 | LSM Tree、極高壓縮、適合 Flash 儲存 |
記住:儲存引擎是表級屬性,同一資料庫可混用,但跨引擎事務不支援。新建表預設 ENGINE=InnoDB,除非有極強理由否則不改。