什么是事务四大特性?用业务案例通俗讲透 ACID

什么是事务四大特性?用业务案例通俗讲透 ACID

"转账一半系统崩了怎么办?"

"两个订单同时抢最后一件库存,超卖谁背锅?"

"查账单的时候,钱还在不在?"

这些问题,本质上都在问一件事:数据库的事务靠不靠谱?

而判断一个事务靠不靠谱,业界有一套黄金标准------ACID。这四个字母,撑起了整个关系型数据库的信任基石。

今天不讲枯燥定义,我们用电商下单、转账、支付这些你每天都在写的业务场景,把 ACID 讲透。


先给一句话人话版定义

特性 英文 一句话解释
原子性 Atomicity 要么全做,要么全不做
一致性 Consistency 数据从一个合法状态变到另一个合法状态
隔离性 Isolation 多个事务互不干扰,像排队一样
持久性 Durability 提交成功,落地生根,断电也不丢

接下来,一个个拆解。


一、原子性(Atomicity):要么都成功,要么都失败

业务场景:转账

A 给 B 转账 100 元。

底层至少两步操作:

css 复制代码
1. A 账户扣 100 元
2. B 账户加 100 元

如果第 1 步成功,第 2 步失败(比如服务宕机、网络抖动)会发生什么?

  • A 少了 100
  • B 没收到钱
  • 钱"人间蒸发"了 😱

这显然不能接受。

原子性如何兜底?

数据库保证:这两步属于同一个事务

ini 复制代码
START TRANSACTION;

UPDATE account SET balance = balance - 100 WHERE id = 'A';
UPDATE account SET balance = balance + 100 WHERE id = 'B';

COMMIT;
  • 两条 SQL 要么一起成功
  • 只要有一条失败,数据库自动执行 ROLLBACK(回滚)
  • 最终结果:钱既没少,也没多,系统回到转账前的状态

✅ 原子性 = "同生共死"

就像火箭发射:要么整体升空,要么原地不动,绝不允许"半空解体"。


二、一致性(Consistency):数据永远"说得通"

业务场景:下单扣库存

用户下单买一件商品,库存从 10 变成 9。

这里有几个"业务规则"(约束):

  • 库存不能为负数
  • 订单金额必须等于商品单价 × 数量
  • 已支付订单必须有对应的支付记录

什么是一致性?

事务执行前后,数据库都必须满足所有业务规则和约束

sql 复制代码
START TRANSACTION;

-- 扣库存
UPDATE product SET stock = stock - 1 WHERE id = 1001;

-- 创建订单
INSERT INTO orders(...) VALUES(...);

COMMIT;
  • 如果库存不足,数据库会直接报错(如 CHECK / 外键 / 应用层校验)
  • 事务回滚,库存还是 10,订单也不会生成
  • 不会出现"库存 -1,订单却不存在"的脏数据

✅ 一致性 = "数据始终讲道理"

⚠️ 注意一个常见误区:

一致性不是数据库自动保证的业务逻辑

而是:

  • 原子性 + 隔离性 + 持久性

  • 再加上你写的正确的业务代码

    共同维护的结果。

换句话说:

ACID 里,A、I、D 是数据库的能力

C 是你和数据库一起守住的底线


三、隔离性(Isolation):并发不乱,各走各的

业务场景:秒杀抢最后一件商品

商品只剩 1 件,同时来了两个请求:

  • 用户 A:下单
  • 用户 B:下单

如果没有隔离性,可能出现这种情况:

css 复制代码
A 查库存 = 1
B 查库存 = 1
A 扣库存 → 0
B 扣库存 → -1 ❌(超卖)

这就是典型的 并发问题

隔离性做了什么?

数据库通过 锁 / MVCC(多版本并发控制) ,让多个事务互相隔离。

InnoDB 默认的 REPEATABLE READ​ 为例:

  • A 的事务开启后,看到库存 = 1
  • B 的事务也被正确隔离
  • 其中一个事务提交后,另一个再操作时会被阻塞或失败
  • 最终:只有一个订单成功,库存从 1 → 0

✅ 隔离性 = "你在操作的时候,别人看不到中间状态"

可以把它想象成:

每个人进了一个"小黑屋"操作数据,关上门干活,干完才开门让别人进来。

当然,隔离级别越高,并发性能越低,这是经典的 CAP 权衡​ 在事务里的体现。


四、持久性(Durability):落盘才是真安全

业务场景:支付成功

用户完成支付,页面提示"支付成功"。

这时候如果数据库服务器突然断电,数据会丢吗?

如果符合持久性,不会丢

数据库是怎么做到的?

  • 事务提交时,不只是改内存
  • 还会把修改记录写入 redo log(重做日志)
  • redo log 是顺序写磁盘,速度很快
  • 即使断电,重启后数据库也会根据 redo log 恢复已提交的数据
perl 复制代码
COMMIT → 写 redo log → 返回客户端成功

所以,哪怕 MySQL 进程崩溃、服务器掉电:

✅ 已经 COMMIT 的数据,一定存在

⚠️ 注意:

  • 持久性 ≠ 立刻刷盘到数据页
  • 而是:提交成功 = 数据库承诺:我能恢复

✅ 持久性 = "说了算,不算赖账"


四兄弟的关系:谁也离不开谁

很多人以为 ACID 是四个独立特性,其实它们是一个整体:

  • 原子性:保证操作不残缺
  • 一致性:是最终目标(数据正确)
  • 隔离性:防止并发破坏一致性
  • 持久性:保证结果不丢失

可以用一句话串起来:

在一个支持隔离性的环境中,通过原子性和持久性,最终达成数据的一致性。


举个完整例子:下单全流程

sql 复制代码
START TRANSACTION;

-- 1. 扣库存
UPDATE product SET stock = stock - 1 WHERE id = 1001 AND stock > 0;

-- 2. 创建订单
INSERT INTO orders(order_no, user_id, amount) VALUES ('ON123', 1, 100);

-- 3. 扣账户余额
UPDATE account SET balance = balance - 100 WHERE id = 1 AND balance >= 100;

COMMIT;

在这个事务里:

  • 原子性:任意一步失败,全部回滚
  • 一致性:库存、订单、余额始终保持业务合法
  • 隔离性:并发下单不会互相覆盖库存
  • 持久性:COMMIT 成功后,哪怕宕机,订单也真实存在

常见误区澄清(面试常问)

1️⃣ 隔离性 = 串行化?

❌ 不是。

  • 串行化是最高隔离级别
  • InnoDB 常用的是 REPEATABLE READ
  • 通过 MVCC 实现高性能并发

2️⃣ 一致性是谁保证的?

✅ 数据库保证约束(唯一、外键、NOT NULL)

✅ 开发人员保证业务逻辑正确

✅ 原子性 / 隔离性 / 持久性是基础

3️⃣ Spring 的 @Transactional 能保证 ACID 吗?

  • 能保证 原子性、隔离性、持久性
  • 一致性 仍然依赖你写的业务代码
  • 比如:你忘了校验余额,数据库也没约束,那一致性照样崩

一句话总结

ACID 不是四个高大上的概念,而是数据库对你做出的四个承诺:

  • 原子性:我不让你留烂摊子
  • 一致性:我只认"讲道理"的数据
  • 隔离性:你们各忙各的,互不添乱
  • 持久性:我说成功,就一定能找回
相关推荐
Slice_cy19 小时前
Mint 自研框架设计与实现:从重复开发走向配置驱动(五)
前端·后端·架构
景同学19 小时前
把 AI 用到线上运维:可行、有效,前提是喂足信息——一次 Full GC 排障实录
java·人工智能·后端
神奇小汤圆20 小时前
MyBatis、MyBatis-Plus、通用 Mapper:一张图说清三者的血缘关系
后端
SamDeepThinking20 小时前
微信支付对接实战:从下单到回调的完整落地过程
后端·程序员·架构
神奇小汤圆20 小时前
架构师必备:分布式锁方案选型
后端
shengjk120 小时前
付费上班的时代,真的来了
后端
玉鸯20 小时前
旧概念还是新范式?Agent 框架集体"图化"背后的矛盾与必然
后端·llm·agent
倾颜21 小时前
断线之后,不要重跑 AI:在 POST + NDJSON 中实现可恢复 Agent 流
前端·后端·agent