| 特性 | MyISAM | InnoDB |
|---|---|---|
| 事務支援 | ❌ 無 | ✅ ACID 完整支援 |
| 行級鎖 | ❌ 僅表級鎖 | ✅ 行級鎖(高並發寫入優勢) |
| 外鍵約束 | ❌ 無 | ✅ 支援 |
| 全文索引 | ✅ 內建(5.6 前) | ✅ 5.6+ 內建,早期需 Sphinx |
COUNT(*) 效能 | ✅ O(1) 直接讀取行數 | ❌ 全表掃描(無 WHERE 時) |
| 主鍵查詢 | 正常 | ✅ 聚簇索引極快 |
| 崩潰恢復 | ❌ 需 REPAIR TABLE,慢、可能丟資料 | ✅ Redo/Undo Log 快速恢復 |
| MVCC 多版本並發 | ❌ 無 | ✅ 讀不阻塞寫、寫不阻塞讀 |
| 資料壓縮 | ✅ myisampack 唯讀壓縮 | ✅ ROW_FORMAT=COMPRESSED |
| 備份工具 | mysqlhotcopy(已棄用) | xtrabackup 熱備份、mysqldump |
COUNT(*) → MyISAM 可考慮COUNT(*) 行為差異
-- MyISAM:直接讀取表元資料中的行數,極快
SELECT COUNT(*) FROM myisam_tbl; -- 0.001s
-- InnoDB:需掃描聚簇索引(或次要索引)計算可見行數
SELECT COUNT(*) FROM innodb_tbl; -- 100萬行約 0.5-2s
-- 有 WHERE 條件時兩者皆需掃描,差異縮小
對策:InnoDB 維護單獨計數表、Redis 計數器、或近似值 SHOW TABLE STATUS(Rows 欄位)。
MAX(id)+1(5.7+ 持久化自增值)DELETE FROM table 行為OPTIMIZE TABLE 或 TRUNCATE)LOAD TABLE FROM MASTER僅支援 MyISAM。InnoDB 需先轉 MyISAM 導入再轉回,但會失去外鍵等特性。
-- InnoDB 无法确定扫描范围时会锁表
UPDATE tbl SET num=1 WHERE name LIKE '%aaa%'; -- 全表鎖風險
對策:避免前導模糊查詢、建立全文索引、或應用層過濾。
[mysqld]
# 核心:刷盤策略,1=最安全(每提交刷盤),0=最高效(每秒刷盤),2=折中
innodb_flush_log_at_trx_commit = 2 # 生產建議 1,高寫入可考慮 2
# 緩衝池:建議 物理記憶體 60-80%
innodb_buffer_pool_size = 4G
innodb_buffer_pool_instances = 8 # 5.5+ 多實例減少爭用
# 日誌檔案大小:總大小 ≈ 緩衝池 25%,單檔 256M-1G
innodb_log_file_size = 512M
innodb_log_files_in_group = 2
# 並發控制
innodb_thread_concurrency = 0 # 0=無限制,5.5+ 建議 0
# 獨立表空間(必開)
innodb_file_per_table = 1
# 避免 autocommit=1 導致單條提交開銷
# 應用層:START TRANSACTION; 批次 INSERT/UPDATE; COMMIT;
# 或會話級:SET autocommit=0;
| 場景 | MyISAM | InnoDB (flush=1) | InnoDB (flush=0) | InnoDB (flush=1 + autocommit=0) |
|---|---|---|---|---|
| 插入 1 萬 | 3s | 219s | 3s | 3s |
| 插入 10 萬 | 29s | 2092s | 29s | 26s |
| 插入 100 萬 | 273s | 未測 | 423s | 379s |
結論:關閉 autocommit 批次提交 是 InnoDB 批量寫入效能的關鍵,innodb_flush_log_at_trx_commit 次之。
| 業務類型 | 推薦引擎 | 理由 |
|---|---|---|
| 電商訂單、金融帳務、核心交易 | InnoDB | 事務、行鎖、崩潰恢復、MVCC |
| 日誌、統計報表、唯讀查詢、全文搜尋(舊版) | MyISAM | COUNT(*) 快、壓縮、全文索引 |
| Session 表、暫存表、快取表 | Memory / InnoDB | Memory 重啟丟失,InnoDB 更穩健 |
| 大數據分析、列式查詢 | ClickHouse / Apache Doris / InnoDB (Columnar) | 超出 MySQL 適用範圍 |
-- 查看表引擎
SHOW TABLE STATUS LIKE 'tbl_name';
SHOW CREATE TABLE tbl_name;
-- 修改引擎(會鎖表重建,大表謹慎)
ALTER TABLE tbl_name ENGINE=InnoDB;
-- 設定預設引擎
[mysqld]
default-storage-engine=InnoDB
ALTER TABLE ... ENGINE=InnoDB 耗時與空間innodb_buffer_pool_size 容納熱點資料LOCK TABLES、COUNT(*)、自增欄位依賴、全文索引替代myisam_recover、調整備份策略為 xtrabackup