先选对存储引擎再谈事务:InnoDB支持事务并维护redo/undo日志、行级锁和聚簇索引,开销高于MyISAM;MyISAM不支持事务,强行使用START TRANSACTION等语句无效。

存储引擎决定事务能否存在,事务机制的开销是在存储引擎之上的——所以先选对存储引擎,再谈事务怎么用。InnoDB 支持事务,MyISAM 不支持;用 MyISAM 强行套事务逻辑,只会让 START TRANSACTION 和 COMMIT 变成无效空操作,还误以为自己“有事务保障”。
为什么 InnoDB 的事务开销比 MyISAM 高
InnoDB 在每次写操作中要维护:redo log(保证崩溃恢复)、undo log(支持回滚和 MVCC)、行级锁结构、聚簇索引组织方式。而 MyISAM 只做表级锁 + 简单的磁盘文件追加。
- 一个
UPDATE在 InnoDB 中可能触发:索引页分裂、缓冲池刷脏、日志刷盘、锁等待检测 - 同样语句在 MyISAM 中只是:获取表锁 → 修改 .MYD 文件 → 释放锁
- 高并发写场景下,InnoDB 的
innodb_flush_log_at_trx_commit设置会显著影响吞吐(设为 2 比 1 快 3–5 倍,但掉电可能丢 1s 日志)
事务隔离级别对性能的实际影响点
不是“级别越高越慢”,而是 READ COMMITTED 和 REPEATABLE READ 在 InnoDB 中实现方式不同,直接影响 undo log 保留时长和一致性读路径。
-
REPEATABLE READ下,事务启动时会固定一个read view,后续所有SELECT都基于它;长事务会让 undo log 无法清理,撑爆ibdata1 -
READ COMMITTED每次SELECT都新建 read view,避免长事务拖累,但频繁快照生成有轻微 CPU 开销 -
SERIALIZABLE会把普通SELECT自动加上共享锁,极易引发锁等待,实际业务中极少使用
什么时候该怀疑是引擎/事务配置惹的祸
遇到这些现象,优先查存储引擎和事务相关配置,而不是一上来优化 SQL:
- 执行
SHOW CREATE TABLE t1发现引擎是MyISAM,但代码里写了BEGIN; UPDATE; COMMIT;—— 这些事务控制完全没生效 -
SHOW ENGINE INNODB STATUS里反复出现TRANSACTIONS区域的lock wait timeout或大量history list length> 10000 -
innodb_buffer_pool_size设得太小(比如仅 128M),又开着autocommit=0批量导入,导致频繁刷脏和日志等待
真正卡顿往往不出现在 SQL 本身,而出现在引擎层对事务语义的兑现过程里——比如一个没提交的事务,正拿着 10 万行记录的 undo log 不放,别的查询就得绕着它走。这种问题不会报错,但会让响应时间飘忽不定。











