acid由innodb引擎保障,myisam不支持事务;原子性依赖undo log但ddl会隐式提交;隔离性默认可重复读,幻读需next-key lock防护;持久性靠redo log刷盘策略,参数设置影响数据安全。

ACID不是抽象概念,而是InnoDB引擎的硬性行为保障
MySQL本身不实现事务,真正扛起ACID的是存储引擎——InnoDB。如果你用的是MyISAM表,哪怕写了BEGIN和COMMIT,也**完全不支持事务**,所有ACID特性形同虚设。确认是否生效,第一件事就是查表引擎:SHOW CREATE TABLE your_table;,确保看到ENGINE=InnoDB。
原子性靠undo log回滚,但DDL语句会偷偷提交事务
原子性(Atomicity)意味着“全做或全不做”,InnoDB通过undo log记录修改前的旧值,一旦执行ROLLBACK就靠它恢复。但这里有个致命陷阱:
-
CREATE TABLE、DROP TABLE、ALTER TABLE等DDL语句,**在事务中执行会自动触发隐式提交**,导致前面所有DML操作立刻落盘,无法回滚 -
TRUNCATE TABLE也是DDL,同样会强制提交,别误以为它和DELETE一样可逆 - 想安全地删数据又保留回滚能力?必须用
DELETE FROM table_name,且确保没开启autocommit=1
隔离性默认是“可重复读”,但幻读仍需Next-Key Lock防御
MySQL默认隔离级别是REPEATABLE READ,它用MVCC解决不可重复读,但**对“幻读”只做部分防护**:普通SELECT不会看到新插入行,可一旦执行UPDATE ... WHERE或SELECT ... FOR UPDATE,若范围条件匹配到新插入的记录,就会暴露幻读。
真正堵住这个口子的是InnoDB的Next-Key Lock(间隙锁 + 记录锁),但它只在WHERE条件命中索引时生效;如果查询走的是全表扫描,间隙锁失效,幻读风险回归。
持久性不等于“写完磁盘”,redo log刷盘策略决定崩溃后能否找回
事务提交后数据“永久保存”,靠的是redo log而非直接写数据文件。它的可靠性取决于innodb_flush_log_at_trx_commit参数:
-
1(默认):每次COMMIT都刷盘,最安全,但IO压力大 -
0:每秒刷一次,崩溃可能丢1秒事务 -
2:写入OS缓存即返回,依赖OS刷盘,崩溃可能丢数据
线上系统别盲目调成0或2——看似快了,但遇到断电或内核panic,COMMIT成功的转账可能人间蒸发。
ACID不是开关,是InnoDB内部日志、锁、版本链协同工作的结果;调参、建索引、选隔离级别,每一步都在动它的神经。最容易被忽略的,其实是事务边界是否真的受控:比如ORM里一个save()背后有没有隐式开启/提交,或者连接池是否复用了已开启却未关闭的事务。










