事务ACID四大特性

一、从一个转账场景开始:为什么要事务?

1.1 没有事务会怎样?

你和朋友聚餐后 AA,你给他微信转账 100 块:

 
-- 银行系统内部做了两步操作:
 
UPDATE account SET balance = balance - 100 WHERE id = 1;   -- 你的账户减 100
 
UPDATE account SET balance = balance + 100 WHERE id = 2;   -- 朋友的账户加 100
 

这中间如果出问题了——

意外场景后果
第一条执行完,第二条执行前,服务器断电你的钱扣了,朋友没收到 — 100 块凭空消失
第一条执行完,第二条执行时违反约束报错同上
两个 SQL 之间,另一个程序改了你朋友的余额数据错乱

两条 SQL 必须要么全成功,要么全失败。 这就是事务。

1.2 事务是什么?

事务 = 把一组 SQL 操作打包成一个”不可分割的整体”。这个整体要么全部执行成功,要么全部撤销回滚,不存在”一半成功一半失败”。

 
-- 用事务包起来
 
START TRANSACTION;
 
  UPDATE account SET balance = balance - 100 WHERE id = 1;
 
  UPDATE account SET balance = balance + 100 WHERE id = 2;
 
COMMIT;   -- 确认,真正写入
 
-- 如果出错就 ROLLBACK,全部撤销
 

通俗比喻:就像婚礼上牧师问”你愿意吗?”

  • 你说”我愿意”→ COMMIT(确认,生效)

  • 你跑出教堂 → ROLLBACK(回滚,就当这事没发生)

  • 不存在”结了一半的婚”


二、ACID 四大特性(必考)

ACID = Atomicity(原子性)+ Consistency(一致性)+ Isolation(隔离性)+ Durability(持久性)

2.1 原子性 Atomicity

要么全做,要么全不做。不存在做一半。

 
转账 100 元的两步:减你的钱 + 加朋友的钱
 
结果只能有两种:
 
  ✅ 两步全完成 → 转账成功
 
  ✅ 两步全撤销 → 回到转账前
 
  ❌ 减了你的钱但没加朋友的钱 → 绝不可能
 

MySQL 怎么实现的:通过 undo log(回滚日志)。每条修改操作前,先把改之前的值记在 undo log 里。需要回滚时,根据 undo log 把数据恢复原样。

 
执行 UPDATE balance = balance - 100 之前:
 
  undo log 记一笔:"balance 原来是 500"
 
  然后改 balance = 400
 
如果回滚:
 
  读 undo log:"哦,原来是 500"→ balance 改回 500
 

undo log 像一个后悔药箱子,每次改数据前先把”旧值”存进去。回滚就是按旧值恢复。


2.2 一致性 Consistency

事务执行前后,数据必须符合同一个业务规则。 规则不会因为事务被打破。

 
规则:账户余额不能为负数
 
事务前 → 双方余额都是正数,符合规则
 
事务中 → 你的余额可能会暂时变成负数
 
事务后 → 要么全部成功(余额都是正数),要么全部回滚(回到原来的正数)
 
总之最后状态一定符合规则,不会出现"你的余额是 -100"
 

通俗比喻:就像玩积木 — 你可以把积木拆散再搭起来,但搭完后积木总数不会多也不会少。

❗ 一致性是结果要求,原子性、隔离性、持久性都是实现手段。经常问”ACID 四个特性的关系”——答案就是:A、I、D 都是为了 C。


2.3 隔离性 Isolation

多个事务同时执行时,互相不干扰。 每个事务都以为自己是唯一在运行的事务。

 
场景:你和另一个人同时给同一个朋友转账
 
没有隔离性时可能出现:
 
  事务A 读余额 = 500(刚被事务B 改了,但还没提交)
 
  事务A 基于 500 做操作
 
  事务B 回滚了,余额其实是 600
 
  事务A 算错了
 
有隔离性时:
 
  事务A 看到的余额 = 600(事务B 的修改在提交前对 A 不可见)
 

MySQL 怎么实现的:通过 MVCC(多版本并发控制)+ 锁。重点详见 MVCC 原理


2.4 持久性 Durability

一旦事务提交成功,数据就永久保存了。 就算数据库立刻崩溃,重启后数据还在。

 
你转账成功后,银行返回"转账成功"
 
即使下一秒机房断电,你的钱仍然在对方账户里
 

MySQL 怎么实现的:通过 redo log(重做日志)。提交事务时,不是直接写数据文件,而是先写 redo log(顺序写,极快),数据文件异步慢慢刷

 
提交一个事务:
 
  ① 把修改内容写到 redo log(顺序追加,飞快)→ 写完了就算提交成功
 
  ② 后台慢慢把数据刷到真正的数据文件
 
崩溃恢复:
 
  重启时读 redo log → 找到已提交但还没真正写入数据文件的修改 → 补写
 

通俗比喻

  • redo log = 餐厅前台小本子,你来点菜,服务员飞快在小本子上记一笔,然后让你坐下等
  • 数据文件 = 后厨,慢慢做菜
  • 点菜后服务员晕倒了(服务器崩溃)→ 醒来后翻小本子,继续把没上的菜补上

2.5 ACID 一张表总结

特性一句话实现手段通俗比喻
原子性全做或全不做undo log后悔药 — 回滚就恢复原样
一致性数据始终符合规则A+I+D 共同保证积木总数量不能变
隔离性并发事务互不干扰MVCC + 锁各自在独立房间办事
持久性提交后就永存redo log餐厅小本子记着,后厨补做

三、一图流(Mermaid)


flowchart LR

    A[事务 ACID] --> B[Atomicity 原子性]

    A --> C[Consistency 一致性]

    A --> D[Isolation 隔离性]

    A --> E[Durability 持久性]

    B --> B1[undo log 回滚]

    C --> C1["结果要求 A+I+D 都是手段"]

    D --> D1[MVCC + 锁]

    E --> E1[redo log 重做]

    style C fill:#ffe0b2

速记卡(面试闪卡)

Q1:一句话讲清「事务ACID四大特性」到底是什么?

A:事务把一组 SQL 打包成不可分割的整体,ACID 保证它要么全成、要么全回滚。

Q2:一、原子性 Atomicity —— 怎么理解?

A:要么全做要么全不做,绝没有”做一半”。MySQL 靠 undo log(后悔药箱子)——改数据前先把旧值存进去,回滚就按旧值恢复。就像婚礼说”我愿意”才生效,跑出教堂就当这事没发生。

Q3:二、一致性与隔离性 —— 怎么理解?

A:一致性是结果要求——事务前后数据必须符合业务规则(如余额不为负),A/I/D 都是为它服务的手段;隔离性是并发事务互不干扰,靠 MVCC+锁,别的事务没提交的修改对你不可见。

Q4:三、持久性 Durability —— 怎么理解?

A:一旦提交就永久保存,立刻断电也在。MySQL 靠 redo log(餐厅小本子)——提交时顺序写日志极快(算成功),后台慢慢刷数据文件;崩溃重启按日志把没落盘的补写。

Q5:四、ACID 关系一张图 —— 怎么理解?

A:一句话:A、I、D 三个小弟都是为了保 C 这个 boss。原子靠 undo log 回滚、隔离靠 MVCC+锁、持久靠 redo log 重做,一致性是它们共同的终点。

Q6:核心速记主线有哪些?

  • 事务 = 一组 SQL 要么全成要么全败

  • 原子性靠 undo log 回滚

  • 一致性是结果要求,AID 都是手段

  • 隔离性靠 MVCC + 锁

  • 持久性靠 redo log 重做

口诀

A:事务打包不分家,

原子 undo 回滚它;

隔离 MVCC 锁护驾,

持久 redo 小本记下。

相关链接