不能只跑sysbench oltp就下结论,因myisam的高qps掩盖了大量.myd/.myi随机写,而innodb的tps略低但innodb_data_writes和innodb_log_writes更平稳;须结合iostat、/proc/diskstats、show global status差值及perf trace等多层指标对比分析。

直接用 sysbench 跑 oltp_write_only 和 oltp_read_write 混合负载,配合 fio 单独压测底层 NVMe 随机写 IOPS,才能真实反映 InnoDB 与 MyISAM 在 NVMe 上的 IO 差异。只看 TPS 或 QPS 数字没意义,关键得拆解到页刷、日志写、索引更新这些底层动作。
为什么不能只跑 sysbench oltp 就下结论
MyISAM 在 sysbench oltp_read_write 中看似 QPS 不低,但背后是大量重复的 .MYD/.MYI 文件随机写;InnoDB 的 TPS 看似略低,但 innodb_data_writes 和 innodb_log_writes 更平稳。不看这些状态变量,就等于只看车速不看发动机转速。
-
SHOW GLOBAL STATUS LIKE 'Innodb_data_writes'和'Innodb_log_writes'必须在测试前后各取一次差值,再除以时间,算出真实每秒物理写次数 - MyISAM 没有 redo log,
Key_writes+Bytes_received(含 INSERT 包)能粗略反推其写放大程度 - 如果
Innodb_buffer_pool_wait_free在测试中持续非零,说明 InnoDB 刷脏跟不上,此时 MyISAM 的“高 QPS”只是把压力甩给了磁盘——它根本没缓存数据页
必须同步采集的底层指标
NVMe 设备的队列深度和延迟特性会放大引擎差异,光看 MySQL 内部计数不够,得看 OS 层是否真压满设备:
- 用
iostat -x 1观察%util和await:NVMe 下%util == 100%且await 才算真正榨干硬件;若 <code>await > 2ms,大概率是调度器没关或innodb_write_io_threads不足 - 查
/proc/diskstats对应 NVMe 设备的第10列(ms spent writing)和第4列(writes completed),算出平均单次写延迟:值低于 100μs 才算 NVMe 正常发挥 - 对比
Innodb_data_fsyncs和系统层fsync()调用次数(用perf trace -e syscalls:sys_enter_fsync -p $(pgrep mysqld)抓),MyISAM 会触发更多 fsync,因为没 WAL 缓冲
如何让对比结果不被 buffer pool 干扰
InnoDB 的 innodb_buffer_pool_size 如果设得太大,会让大部分测试数据驻留内存,掩盖真实磁盘 IO 行为;MyISAM 的 key_buffer_size 只缓索引,数据文件始终直写——这个不对称必须控制。
- 把
innodb_buffer_pool_size设为远小于测试数据集(例如数据集 20GB,只设 2G),确保每轮sysbench run都有大量 page miss 和脏页刷盘 - MyISAM 测试前执行
echo 3 > /proc/sys/vm/drop_caches,清掉 page cache,否则它的 .MYD 文件读会走系统缓存,虚高吞吐 - 两个引擎都用相同
--table-size=1000000 --tables=16,避免 MyISAM 单表锁在高并发下因锁等待拉低数字,扭曲 IO 特性
最容易被忽略的 NVMe 特定陷阱
NVMe 的低延迟不是万能的,InnoDB 和 MyISAM 都可能因配置不当让它“空转”:
- InnoDB 的
innodb_flush_neighbors = 1(默认值)在 NVMe 上必须关死:它会强制合并邻近页刷盘,制造本不必要的额外 IO,而 NVMe 根本不需要减少寻址 - MyISAM 的
delay_key_write = ON在 NVMe 上反而有害:它延迟索引写入,导致 crash 后索引损坏概率升高,且无法利用 NVMe 的快速 fsync 优势 - 两个引擎都必须确认
innodb_flush_method = O_DIRECT(InnoDB)和myisam_recover_options = BACKUP,FORCE(MyISAM),否则 Linux page cache 会干扰真实 IO 路径
真正决定 IO 表现的,从来不是“SSD 多快”,而是引擎怎么用这块 SSD——InnoDB 把随机写转成顺序 redo log,MyISAM 把每次 INSERT 拆成两份随机写,这个根本差异在 NVMe 上只会更刺眼,而不是被抹平。











