InnoDB是MySQL 5.5+默认且唯一推荐的事务引擎,因其支持行级锁、MVCC、外键和完整ACID;MyISAM仅支持表级锁、无事务、易丢数据,混用或误用将引发线上事故。

MySQL 的存储引擎不是可有可无的插件,而是直接决定你能不能用事务、数据会不会丢、并发读写是否安全的核心组件。选错引擎,InnoDB 和 MyISAM 表混用,或者误以为“开了事务就一定原子”,都是线上事故常见起点。
为什么 InnoDB 是默认且几乎唯一推荐的事务引擎
InnoDB 是 MySQL 5.5+ 默认引擎,它把索引和数据一起存(聚簇索引),支持行级锁、MVCC、外键和完整的 ACID 实现。而 MyISAM 只支持表级锁、无事务、崩溃后容易坏表——哪怕只是断电,也可能丢失最后几条 INSERT 的数据。
-
MyISAM的AUTO_INCREMENT是表级缓存,高并发插入可能卡住;InnoDB是行级 + 意向锁,冲突更少 -
InnoDB的REPLACE INTO或INSERT ... ON DUPLICATE KEY UPDATE能安全处理重复键,MyISAM在此场景下可能触发非预期的删除+插入顺序 - 即使只读场景,也别迷信
MyISAM更快:现代 SSD + 缓存下,InnoDB的随机读性能差距极小,且避免了修复表(REPAIR TABLE)这种运维黑洞
BEGIN / START TRANSACTION 后,什么才算真正开启一个事务
事务不是靠语句开头几个字就生效的,它受 autocommit 状态和存储引擎双重约束。执行 BEGIN 本身不启动事务,只是把当前会话的 autocommit 设为 0;如果连的表是 MyISAM,哪怕写了 COMMIT,也不会回滚任何东西。
- 检查当前事务状态:
SELECT @@autocommit, @@in_transaction; -
SET autocommit = 0后所有 DML 都进入隐式事务,直到显式COMMIT或ROLLBACK;但 DDL(如ALTER TABLE)仍会自动提交,无法回滚 - 长事务(>10 秒)会拖慢 purge 线程,导致
ibdata1文件持续膨胀、历史版本链过长,最终拖垮查询性能
ACID 里最容易被误解的是 “I”(隔离性)和 “D”(持久性)
ACID 不是开关,而是由引擎实现 + 隔离级别 + 刷盘策略共同决定的行为边界。READ COMMITTED 下不会出现脏读,但幻读依然存在;innodb_flush_log_at_trx_commit=1 才保证事务提交后日志落盘,否则断电可能丢最近 1 秒的已提交事务。
-
REPEATABLE READ是InnoDB默认级别,靠 MVCC + next-key lock 解决幻读,但仅限当前读(SELECT ... FOR UPDATE);快照读(普通SELECT)看到的是事务开始时的一致视图 -
innodb_doublewrite=ON必须开着——它防止页写入一半崩溃导致数据页损坏,关掉等于拿一致性换一点点写入延迟 -
sync_binlog=1和innodb_flush_log_at_trx_commit=1配合,才能在主从切换时保障 binlog 和 redo log 严格一致,否则可能丢事务或主从不一致
真正难的不是记住 ACID 定义,而是当 SELECT 突然变慢、UPDATE 开始锁表、或者从库延迟飙升时,能快速判断是隔离级别副作用、刷盘参数松动,还是引擎本身不支撑这个业务模型。










