理論比較需實測驗證。本文記錄真實硬體環境下 MyISAM 與 InnoDB 插入效能對比,深度分析 innodb_flush_log_at_trx_commit、innodb_buffer_pool_size、autocommit 關鍵參數影響。
| 項目 | 配置 |
|---|---|
| CPU | AMD 2500+ (1.8GHz) |
| 記憶體 | 1GB DDR |
| 硬碟 | 80GB IDE |
| OS | Windows XP SP2 |
| PHP | 5.2.1 |
| MySQL | 5.0.37 |
| Web | IIS 6 |
-- MyISAM 表
CREATE TABLE `myisam` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`content` text,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=gbk;
-- InnoDB 表
CREATE TABLE `innodb` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`content` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
-- 測試資料
$name = "heiyeluren";
$content = "MySQL支援多種儲存引擎...(約 2KB 文本)";
| 資料量 | MyISAM (筆/秒) | InnoDB (筆/秒) | 倍數差距 |
|---|---|---|---|
| 1 萬 | 3 | 219 | InnoDB 快 73x |
| 10 萬 | 29 | 2,092 | InnoDB 快 72x |
| 100 萬 | 287 | 不敢測 (極慢) | — |
⚠️ 此結果**反常識** (InnoDB 遠快於 MyISAM),原因:測試程式碼可能未提交交易、或 MyISAM 表鎖爭用嚴重。實際生產中 flush_log_at_trx_commit=1 通常導致 InnoDB 寫入較慢。
| 資料量 | MyISAM | InnoDB | 說明 |
|---|---|---|---|
| 1 萬 | 3 | 3 | 持平 |
| 10 萬 | 30 | 29 | 持平 |
| 100 萬 | 273 | 423 | InnoDB 略快 |
關鍵發現:**innodb_flush_log_at_trx_commit=0 讓 InnoDB 效能追平甚至超越 MyISAM**,代價是崩潰可能丟失 1 秒交易。
| 資料量 | InnoDB |
|---|---|
| 1 萬 | 3 |
| 10 萬 | 33 |
| 100 萬 | 607 |
緩衝池過大無顯著提升,受限於實體記憶體與 32 位元限制。
| 資料量 | InnoDB |
|---|---|
| 1 萬 | 3 |
| 10 萬 | 26 |
| 100 萬 | 379 |
手動交易批次提交 (autocommit=0) 是 InnoDB 批次寫入的正確姿勢,效能接近 flush_log=0 但資料安全性高。
| 值 | 行為 | 效能 | 資料安全 | 適用場景 |
|---|---|---|---|---|
| 1 (預設) | 每提交 fsync 刷盤 | 最低 | 最高 (零丟失) | 核心交易、金融、訂單 |
| 2 | 提交寫 OS 快取,每秒 fsync | 中等 | OS 崩潰丟 1 秒 | 可接受秒級丟失的業務 |
| 0 | 提交寫 Log Buffer,每秒寫 OS 快取並 fsync | 最高 | OS 崩潰丟 1 秒 | 日誌、監控、非核心數據 |
-- ❌ 預設 autocommit=ON:每 INSERT 一次 fsync (flush_log=1 時)
INSERT INTO t VALUES (...); -- 1 次 fsync
INSERT INTO t VALUES (...); -- 1 次 fsync
-- ✅ 手動交易批次提交
SET autocommit = 0;
START TRANSACTION;
INSERT INTO t VALUES (...); -- 1000 筆
INSERT INTO t VALUES (...);
COMMIT; -- 1 次 fsync (flush_log=1)
-- 效能提升 100-1000x
[mysqld]
port = 3306
basedir = "C:/mysql50/"
datadir = "C:/mysql50/Data/"
default-character-set = gbk
default-storage-engine = INNODB
sql_mode = "STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections = 100
query_cache_size = 0
table_cache = 256
tmp_table_size = 50M
thread_cache_size = 8
myisam_max_sort_file_size = 100G
myisam_sort_buffer_size = 100M
key_buffer_size = 82M
read_buffer_size = 64K
read_rnd_buffer_size = 256K
sort_buffer_size = 256K
innodb_additional_mem_pool_size = 4M
innodb_flush_log_at_trx_commit = 1
innodb_log_buffer_size = 2M
innodb_buffer_pool_size = 159M
innodb_log_file_size = 80M
innodb_thread_concurrency = 8
[mysqld]
# 基礎
innodb_buffer_pool_size = 64G # 128GB 記憶體機器
innodb_log_file_size = 4G
innodb_log_files_in_group = 4
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_file_per_table = ON
innodb_io_capacity = 20000 # NVMe SSD
innodb_io_capacity_max = 40000
innodb_page_cleaners = 4
innodb_read_io_threads = 16
innodb_write_io_threads = 16
innodb_buffer_pool_instances = 8
# 連線
max_connections = 2000
thread_cache_size = 100
# 查詢快取 (5.7+ 建議關閉)
query_cache_type = OFF
query_cache_size = 0
# 臨時表
tmp_table_size = 256M
max_heap_table_size = 256M
# 日誌
slow_query_log = 1
long_query_time = 1
log_queries_not_using_indexes = 1
SET autocommit=0; START TRANSACTION; ... COMMIT;,否則效能極差innodb_io_capacity,大記憶體需多實例實測數據證明:InnoDB 配合正確參數 (批次交易、足夠緩衝池、合理 flush 策略) 效能不遜於 MyISAM,且提供交易、行鎖、崩潰恢復等企業級特性。**不要用錯誤配置測出的數據否定 InnoDB**,要用正確配置釋放其真實實力。