MySQL事务的特性就是
ACID—— 它不是抽象概念,而是 InnoDB 存储引擎用
undo log、
redo log、
锁机制和
doublewrite buffer等实实在在的组件硬扛出来的。你写的每一条
START TRANSACTION,背后都在触发这些机制协同工作。
原子性靠 undo log 回滚链实现
事务中任意一步失败(比如
UPDATE违反唯一约束),InnoDB 不会只“撤掉这一步”,而是根据该事务的
undo log记录,把所有已做的变更逆向还原——就像倒带一样回到事务开始前的状态。
undo log是在事务执行过程中实时写入的,即使事务中途崩溃,重启后也能靠它回滚 大事务(比如批量更新百万行)会产生大量
undo log,可能占满
undo tablespace,导致
ERROR 1205 (HY000): Deadlock found when trying to get lock或
Lock wait timeout exceeded
ROLLBACK不是“删除日志”,而是用日志重放反向操作;所以回滚大事务可能比提交还慢,且引发高 I/O
隔离性由 MVCC + 行锁共同控制
InnoDB 默认隔离级别是
REPEATABLE READ,它不靠锁住整张表来实现,而是结合多版本并发控制(
MVCC)和
next-key lock来平衡安全与性能。 同一事务内多次
SELECT能看到相同快照,靠的是事务启动时分配的
read view,而不是加读锁 但
UPDATE/
DELETE仍会加行锁或间隙锁,避免幻读;如果只靠 MVCC,
INSERT就可能绕过检查造成数据不一致 切忌在事务里混用
SELECT ... FOR UPDATE和普通
SELECT:前者会升级为当前读,破坏一致性快照,容易引发死锁
持久性依赖 redo log 的两阶段提交
你执行
COMMIT后立刻能查到新数据,并不意味着数据已刷进表空间文件——真正落盘靠的是
redo log的
prepare → commit两阶段写入。 只要
redo log的
commit记录写成功(默认
innodb_flush_log_at_trx_commit = 1),即使 MySQL 崩溃,重启时也能从日志恢复已提交事务 设成
0或
2会提升写入性能,但崩溃可能丢失最多 1 秒事务——线上交易系统严禁这么配
redo log空间有限(默认 48MB),写满会阻塞事务,监控
Innodb_os_log_pending_fsyncs和
Innodb_log_waits很关键
一致性是 ACID 的结果,不是独立机制
Consistency不像其他三项有专属日志或锁结构,它是原子性、隔离性、持久性 + 业务逻辑 + 数据库约束(主键、外键、CHECK)共同达成的效果。 转账例子中“总额不变”不是数据库自动保证的,而是靠你在事务里写对了两条
UPDATE,再配合原子性和隔离性不被干扰 InnoDB 会强制校验外键、唯一索引等约束,一旦违反就直接报错并触发回滚——这是它保障一致性最实在的动作 如果你在事务里绕过约束(比如用
INSERT IGNORE忽略重复键),或在应用层做计算(如余额 = SUM(transactions)),那数据库就管不了“逻辑一致性”了 真正难的从来不是记住 ACID 四个字母,而是理解:每个
COMMIT都在调用磁盘、内存、锁管理器三套系统协同工作;而任何一个环节配置不当(比如关了
sync_binlog又没开半同步复制),都可能让“已提交”的事务在主从切换后人间蒸发。
