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:依据默认自动提交、显式多语句事务、错误处理和隐式提交规则,解释正文中事务的开始、结束及异常后的处理边界。
相关面经
24 篇字节跳动
后端你对事务的理解.
模算归巢
测试开发工程师了解事务吗
拼多多、荣耀、立元科技、得物、华橙
数据库事物
字节跳动
Agent 开发Redis 有事务吗?它与 MySQL 事务有什么区别?
字节跳动
后端开发实习生MySQL怎么保证事务中的操作全部成功或全部失败?
展开剩余 19 篇面经
蚂蚁集团
数据库的四个特性,具体分别是怎么去实现的
蚂蚁集团
ACID,原子性一致性怎么实现的
科大讯飞
Java 开发工程师MySQL的事务
中科创达
后端开发工程师(AI / RAG 方向)数据库事务的 ACID 四大特性分别是什么?
虾皮
你提到事务,详细讲讲你项目中事务怎么做的
快手
后端开发工程师华为
通用软件开发3\. MySQL 如何通过事务、隔离级别和锁解决并发修改问题?
百度
后端开发10 事务怎么开启 特性 隔离级别
ThunderBit
AI 后端讲讲你对 ACID 的理解?各特性分别怎么实现的?
虾皮
后端实习MySQL 中事务是如何实现的?
字节跳动
后端开发工程师(AI)事务了解吗?简单讲一下?
百度
智能体开发MySQL事务特性及实现
腾讯
后端开发实习生一致性怎么保证?代码中怎么实现?
京东
后端InnoDB为什么支持事务,有什么锁,有什么索引,索引实现场景,为什么失效,怎么不失效
字节跳动
字节跳动、腾讯
MySQL的事务了解过吗?
飞猪
Java 后端开发mysql如何实现事务的,底层
超星集团
Java开发项目中有用到事务吗?如何保证一致性?
字节跳动
AI 开发工程师mysql事务







