innodb在高负载下更省cpu,因其将锁竞争、日志刷盘和缓存管理转为异步/批量行为;myisam表级锁、os缓存抖动及无事务协调导致cpu空转等待与频繁上下文切换。

InnoDB 在高负载下比 MyISAM 更节省 CPU 资源,根本不是因为“更先进”,而是它把锁竞争、日志刷盘和缓存管理这些开销,从 CPU 等待态转为可控的异步/批量行为;而 MyISAM 表级锁 + OS 文件缓存抖动 + 无事务协调机制,反而让 CPU 长时间空转等待或反复上下文切换。
表级锁导致 CPU 大量空转在 Waiting for table level lock
MyISAM 写操作一上来就申请整张表的 WRITE LOCK,后续所有请求(无论读写)都卡在锁等待队列里。MySQL 线程状态变成 Locked 或 Waiting for table level lock,但 CPU 并不真正执行 SQL,而是在内核态轮询或休眠唤醒——这会拉高 show processlist 中的 Time 值,同时观测到 vmstat 的 wa(I/O wait)不高但 sy(system CPU)偏高,说明大量时间花在锁调度和上下文切换上。
- 并发 INSERT 时,哪怕只有一行不同,MyISAM 也强制串行化,CPU 无法并行处理
- 一个慢 SELECT 正在扫全表,所有 INSERT 都得等它结束——CPU 看似闲着,实则被线程调度器反复唤醒检查锁状态
-
SHOW ENGINE INNODB STATUS里几乎看不到这类锁等待,因为 InnoDB 的行锁是记录粒度,冲突少、等待短、释放快
日志刷盘方式差异直接决定 CPU 刷写负担
InnoDB 的 redo log 是顺序写、内存缓冲+组提交机制;MyISAM 没有事务日志,但每次 INSERT 或 UPDATE 都要同步更新索引文件(.MYI),且依赖 key_buffer_size 缓存——一旦缓存命中率低,就会触发大量随机磁盘写,而 MySQL 进程必须同步等待 fsync 完成,CPU 在此期间持续阻塞。
-
innodb_flush_log_at_trx_commit=1下,InnoDB 仍能靠log buffer和后台log writer线程合并刷盘,减少系统调用次数 - MyISAM 的
myisam_flush_method即使设为O_DIRECT,也无法规避索引块的随机写放大,尤其当KEY_BLOCK_SIZE小或索引深度大时,CPU 花在地址计算和 buffer copy 上的时间明显上升 - 观察
perf top可见 MyISAM 负载下__GI___libc_write和fsync占比远高于 InnoDB
缓冲池 vs OS 文件缓存:谁让 CPU 更忙?
InnoDB 把数据页和索引页统一管在 innodb_buffer_pool 里,LRU 管理、预读、change buffer 合并都是可控的后台动作;MyISAM 只缓索引,数据文件(.MYD)完全甩给 OS page cache,结果就是缓存抖动剧烈,CPU 不得不频繁处理缺页中断和 dirty page 回写调度。
- MyISAM 高并发读时,
Key_reads暴涨但Key_read_requests不高 → 索引块反复换入换出,CPU 花在 page fault 处理上 - InnoDB 缓冲池满后,淘汰策略由内部 LRU list 控制,不会触发 OS 层 global reclaim,避免影响其他进程
- 用
cat /proc/[pid]/maps | grep -i 'mapped'对比可见:MyISAM 进程 RSS 低但 mapped file 区域巨大,对应大量 page cache 锁定,间接抬高整体系统 CPU 调度压力
事务边界让 CPU 工作更“整块”
InnoDB 的事务把多个语句打包成一次 redo 写入、一次 undo 记录、一次 buffer pool 修改;MyISAM 每条语句都是独立动作,没有 batch 机会,每插入一行就要更新索引树路径、刷新脏块、触发 checkpoint 判定——这些细碎操作在高频写入下对 CPU 是持续毛刺。
- 批量 INSERT 用
BEGIN; ...; COMMIT包裹后,InnoDB 可合并 change buffer 更新、延迟二级索引写入;MyISAM 即使加了INSERT DELAYED(已废弃)也做不到类似效果 - MyISAM 的
AUTO_INCREMENT是表级互斥锁实现,高并发插入时争用auto_inc_mutex,perf record -e 'sched:sched_stat_sleep'可见大量线程睡眠等待 - InnoDB 的自增主键是无锁预分配(
innodb_autoinc_lock_mode=2),CPU 几乎不为此付出额外代价
innodb_flush_log_at_trx_commit=2、有没有把 innodb_buffer_pool_size 设够、有没有避免 WHERE 条件导致全表扫描——这些配置和 SQL 写法,比选哪个引擎更能决定 CPU 跑多快。











