MySQL 事务如何工作,ACID 特性如何保证?
未标记
考查重点:回滚、恢复与并发隔离。undo 支持回滚和版本,redo 支持持久恢复,锁与 MVCC 管并发,约束守业务合法性;保证还受日志配置影响
本题目录
参考答案
核心回答
以 MySQL 8.4 的 InnoDB 普通持久表为例,事务把一组操作放进同一个提交或回滚边界,再由 undo、redo、MVCC、锁和约束共同支撑 ACID。
默认 autocommit=1,普通 SQL 语句各自构成一个事务。需要“扣库存和写订单一起成功”时,应显式开启事务,全部成功后 COMMIT,失败则 ROLLBACK。
- 原子性 A:事务内的修改作为一个整体提交,回滚时撤销未提交的修改。
InnoDB通过undo记录回滚所需的信息;崩溃恢复时也要处理未完成事务,避免留下半个事务的结果。 - 一致性 C:事务应让数据从满足约束和业务规则的状态,变成另一个满足规则的状态。唯一键、外键等约束由数据库检查,“库存不能超卖”等规则还需要应用写对
SQL、判断执行结果,并选择合适的并发控制。 - 隔离性 I:控制并发事务之间能看到什么、哪些操作需要互相等待。
InnoDB通过MVCC提供一致性读,通过锁协调加锁读和写操作,具体行为取决于隔离级别。 - 持久性 D:事务成功提交后,即使进程崩溃,也应能恢复其结果。核心是
redo与预写日志原则:相关日志先持久化,数据页可以稍后刷盘,重启时根据日志恢复。
所以不能把 ACID 全归给 redo,也不能说“开了事务就天然满足所有业务规则”。事务边界、SQL 逻辑、隔离方式和持久化配置都要配合。
进一步解释
一次更新中,日志和数据页怎样配合?
更新通常先作用于 Buffer Pool 中的数据页,形成脏页,同时生成相应的 undo 和 redo 信息。undo 支持撤销,也为 MVCC 提供历史版本;redo 支持崩溃后的重做。它们的职责不同,undo 也不是把原 SQL 换个方向再执行一遍。
提交不需要把本事务涉及的所有脏页立刻写回数据文件。采用持久化提交策略时,先保证恢复所需的日志落盘,再向客户端确认;之后后台逐步刷脏页。崩溃恢复既要恢复尚未写入数据文件的修改,也要处理未提交事务,不能简单理解成“redo 中只会有已提交事务”。
开启 binlog 时,还要协调 InnoDB 事务与 binlog 的提交结果,供崩溃恢复和复制使用。MySQL 的内部两阶段提交处理的是这两者的协同,并不会自动把 Redis、HTTP 调用或其他数据库也纳入同一个本地事务。
隔离为什么同时需要 MVCC 和锁?
在 READ COMMITTED 下,普通一致性读每次使用新的快照;在默认的 REPEATABLE READ 下,同一事务的普通一致性读通常沿用第一次这类读取建立的快照。不能把快照建立时间一概说成执行 BEGIN 的那一刻。
SELECT ... FOR UPDATE 和更新语句采用加锁规则,不能套用普通快照读的全部结论。它们可能等待冲突事务结束;锁的范围还受索引、查询条件和隔离级别影响。MVCC 减少了普通读与写之间的阻塞,并没有消除所有并发冲突。
用下单说明事务边界
一个参考流程是:开启事务,按“库存足够”的条件扣减库存,检查影响行数,成功后写入订单,最后提交。扣减失败则结束流程;订单写入失败则回滚前面的扣减。条件更新及结果判断负责业务正确性,事务负责这组数据库修改一起提交或撤销。
数据库报错时,要区分“当前语句失败”和“整个事务已经回滚”。不同错误的处理方式不同,应用不能捕获异常后不作判断就继续提交。部分 DDL 还会隐式提交,也不能随意夹进上述业务事务。
常见追问
怎样配置才能尽量保住已确认提交的数据?
对需要持久化提交的 InnoDB 业务,通常使用 innodb_flush_log_at_trx_commit=1;启用 binlog 时配合 sync_binlog=1。放宽刷盘策略可能丢失已确认提交的近期事务,损失窗口也不应机械写成“最多一秒”。这些保证仍以操作系统和存储正确兑现刷盘为前提,不能替代备份及容灾。
为什么事务都成功了,库存仍可能不对?
事务可以原子地提交一段写错的业务逻辑。例如先普通查询库存,再无条件按旧值覆盖,即使两步都在事务中,也可能产生并发问题。应把业务条件放进更新语句,或采用合适的锁、版本校验等方式,而不是只依赖 BEGIN 和 COMMIT。
参考资料
- 国内:JavaGuide:MySQL 常见面试题:事务与转账部分用于说明多条操作的提交边界,以及 ACID 四项性质分别约束什么。
- 国内:JavaGuide:MySQL 日志详解:采用 redo、undo、binlog 和两阶段提交各节,串起回滚、崩溃恢复与提交协同;刷盘条件以 MySQL 8.4 官方说明为准。
- 国内:小林 coding:事务隔离级别是怎么实现的?:采用 ACID、并发读写问题及多版本读取的解释,说明隔离与业务一致性各自解决的问题。
- 国外:MySQL 8.4:InnoDB and the ACID Model:核对事务、隔离、崩溃恢复与持久化配置共同参与 ACID,以及可靠性取决于软硬件条件。
- 国外:MySQL 8.4:autocommit, Commit, and Rollback:依据默认自动提交、显式多语句事务、错误处理和隐式提交规则,解释正文中事务的开始、结束及异常后的处理边界。




