mysql事务的acid指原子性、一致性、隔离性、持久性:原子性保证全成功或全失败;一致性依赖其他三性及约束达成业务规则;隔离性通过mvcc和锁解决并发冲突;持久性由redo log刷盘保障崩溃不丢数据。

MySQL事务的四个核心特性到底指什么
MySQL事务的ACID不是抽象概念,而是InnoDB引擎在崩溃恢复、并发读写、异常中断等真实场景下必须守住的四条底线。它们各自解决一个具体问题:
- 原子性(Atomicity):保证“全成功或全失败”。比如转账时扣款和存款必须绑定,不能只执行一半。
- 一致性(Consistency):不是数据库自动保证的“业务正确”,而是靠原子性+隔离性+持久性+约束(如外键、CHECK)共同支撑的最终结果。例如转账前后总金额不变,是代码逻辑+事务机制+约束校验一起达成的。
-
隔离性(Isolation):解决并发读写冲突。默认
REPEATABLE READ级别下,同一个事务内多次SELECT看到的数据版本一致,靠MVCC + undo log实现;而写操作则依赖行锁、间隙锁防止幻读。 -
持久性(Durability):只要
COMMIT返回成功,即使立刻断电,重启后数据也不会丢——这靠的是redo log刷盘(由innodb_flush_log_at_trx_commit=1保障)。
undo log和redo log分别管什么,为什么不能少
很多人混淆这两个日志,其实分工非常明确:
-
undo log是“回滚凭证”:记录修改前的旧值(比如UPDATE前的整行数据),用于ROLLBACK或MVCC构造历史版本。它存在系统表空间里,事务提交后不会立刻删除,要等Purge线程异步清理。 -
redo log是“重做凭证”:记录物理页修改(比如“第5号页偏移量128处写入0x3A”),只管“怎么把内存里的脏页变化安全落地”。它不负责回滚,也不参与MVCC,只服务崩溃恢复。 - 两者缺一不可:没有
undo log,事务失败就无法回退;没有redo log,Buffer Pool里的修改一旦宕机就全丢,COMMIT就成空话。
为什么SET autocommit=0后,DDL语句还会自动提交
这是InnoDB的硬性规则,不是bug。所有DDL操作(如CREATE TABLE、ALTER TABLE、DROP INDEX)都会隐式触发COMMIT,哪怕你已经START TRANSACTION了。
- 原因在于DDL会重建表结构或元数据,涉及存储引擎层状态变更,无法被普通事务包裹。
- 后果很实际:如果你在事务中先
UPDATE再ALTER TABLE,前面的UPDATE会立刻生效,无法通过后续ROLLBACK撤销。 - 规避方法只有两个:把DDL单独放在独立连接里执行,或用
pt-online-schema-change等工具做无锁变更。
隔离级别选错,查不到数据却以为是BUG
最常见踩坑是误以为READ COMMITTED比REPEATABLE READ“更安全”,结果发现同一事务内两次SELECT结果不同,怀疑数据丢了。
-
REPEATABLE READ(InnoDB默认):事务启动时生成一个全局Read View,后续所有SELECT都基于这个快照,所以不会不可重复读。 -
READ COMMITTED:每次SELECT都生成新Read View,能看到其他事务刚COMMIT的数据——这正是“不可重复读”的定义,但它是符合标准的正常行为。 - 真正要注意的是:如果业务依赖“事务内读一致性”(比如先查余额再扣款),就不能随意切到
READ COMMITTED,否则可能多扣或少扣。
undo log没被Purge完,会导致history list堆积,拖慢查询;又比如gap lock只在REPEATABLE READ下生效,换到READ COMMITTED后幻读风险就回来了——这些都不是调个参数就能解决的,得看懂它在做什么。










