MyISAM不支持事务,因缺失undo log、redo log及行级锁等ACID核心组件,即使执行BEGIN/COMMIT也无效;InnoDB则通过undo log、redo log、锁机制和MVCC四者协同实现ACID。

因为ACID不是靠“加个开关”就能启用的特性,而是依赖一套协同工作的底层组件——只有InnoDB在MySQL 5.5+中完整集成了这些组件;MyISAM、Memory、Archive等引擎缺少其中关键一环或多环,事务行为根本无法成立。
为什么MyISAM执行BEGIN/COMMIT也没用?
MyISAM压根没实现事务所需的日志和锁机制:它没有undo log,所以ROLLBACK只是被忽略;没有redo log,崩溃后无法恢复未刷盘的修改;锁粒度是表级,且不支持MVCC或隔离级别切换。哪怕你写了BEGIN和COMMIT,MySQL Server层会照单接收语法,但InnoDB以外的引擎根本不响应事务控制指令。
验证方法很简单:SHOW CREATE TABLE your_table; 看输出里是不是 ENGINE=InnoDB;如果不是,所有事务语句都只是“假动作”。
InnoDB的ACID靠哪几个核心组件落地?
不是单一模块,而是四件套咬合运行:
-
undo log:写在修改前,支撑原子性和MVCC快照读 -
redo log:WAL机制保障持久性,innodb_flush_log_at_trx_commit=1才真正满足D - 行级锁 +
next-key lock:配合MVCC实现可重复读,堵住幻读缺口 - 约束校验(如
FOREIGN KEY)+ 原子性 + 隔离性:三者叠加才达成一致性,不是引擎单独保证
缺任何一个,ACID就塌一角。比如关掉innodb_doublewrite=OFF,可能因部分页写失败导致数据页损坏——这直接动摇持久性和一致性根基。
DDL语句为什么在事务里会“突然提交”?
这是InnoDB对DDL的硬性设计:CREATE TABLE、ALTER TABLE、TRUNCATE TABLE等操作会触发隐式提交,不管当前是否在BEGIN之后。原因在于DDL要重建元数据、重分配空间、甚至重建索引树,无法回滚到中间状态。
后果很直接:如果你在事务里先UPDATE再ALTER TABLE,UPDATE立刻落盘,ROLLBACK已无效。想安全删数据?必须用DELETE FROM,且确认autocommit=0且没混入任何DDL。
最容易被忽略的,其实是事务边界是否真由你掌控——ORM里一次save()可能自动开启又提交事务,连接池复用时上一个连接残留的未提交事务也可能污染当前操作。ACID从不自动生效,它只在你清楚每条SQL背后引擎行为、日志策略和锁范围时,才真正可靠。


















