0Pricing
SQL Interview Prep · 课时

ACID 属性详解

结合具体示例学习原子性、一致性、隔离性和持久性。

ACID 属性详解 是 CoddyKit 上的免费 SQL Interview Prep 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Interview Prep 课程共包含 4 节课。

面试官为何询问 ACID

当资深面试官说“请逐一讲解 ACID”时,他们并不是在考您是否记住了四个词,而是想了解,当许多用户同时访问数据库时,您是否理解数据库能够保证的内容。

ACID 代表原子性、一致性、隔离性和持久性。每个事务型数据库(PostgreSQL、MySQL/InnoDB、SQL Server、Oracle)都会为事务中封装的操作承诺这四项属性。

最有说服力的回答会将每个字母与它所防止的具体故障联系起来。接下来的场景正会这样展开。

什么是事务

事务是一个工作单元,数据库会将其视为一个不可分割的整体。您可以使用 BEGIN 开启事务,执行一条或多条语句,然后使用 COMMIT 使更改永久生效,或使用 ROLLBACK 丢弃所有更改。

经典示例是银行转账:从一个账户扣款,再向另一个账户入账。两步必须同时成功,否则就都不能发生。事务就是让您能够做出这一保证的封装层。

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

A = 原子性

原子性意味着事务要么全部成功,要么全部失败。如果任何语句执行失败,或者服务器在执行过程中崩溃,那么该事务中的所有更改都会被回滚,就好像事务从未开始过一样。

在转账示例中,如果扣款成功后入账失败,原子性会保证扣款也被撤销。您不会因为一次未完成的操作而损失资金。

面试表述:“原子性确保事务要么作为整体提交,要么完全不提交,不会留下部分状态。”

原子性实战

这里的第二次更新违反了检查约束(余额不能为负数)。数据库会中止事务,而 ROLLBACK 也会撤销第一次更新。

面试时要抓住的重点是:回滚之后,账户 1 仍然保留原始余额。表中不存在部分写入的结果。

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- next line fails: balance would go below 0
UPDATE accounts SET balance = balance - 999999 WHERE id = 2;
ROLLBACK;  -- account 1 is restored to its original balance

C = 一致性

一致性意味着事务会将数据库从一个有效状态转变为另一个有效状态。每个已提交的事务都必须遵守所有已定义的规则:约束、外键、触发器和级联。

如果事务会导致某个约束被违反(例如出现孤立外键、重复主键或失败的 CHECK),数据库就会拒绝提交该事务。

需要说明的细节:数据库会执行已声明的规则,但应用层的不变量(“一个用户最多可以拥有 3 个活跃会话”)由您负责,除非您将其建模为约束。

由约束保证的一致性

一致性主要来自您定义的数据库模式规则。下面的外键保证您永远不能为不存在的客户插入订单。

如果插入操作引用了不存在的客户,事务就会失败,原子性会将其回滚,从而保持一致性。这就是面试官会说原子性和一致性协同工作的原因。

CREATE TABLE orders (
  id INT PRIMARY KEY,
  customer_id INT NOT NULL REFERENCES customers(id),
  amount NUMERIC(10,2) CHECK (amount > 0)
);

-- This fails if customer 999 does not exist, keeping data consistent
INSERT INTO orders (id, customer_id, amount) VALUES (1, 999, 50.00);

I = 隔离性

隔离性意味着并发事务不会相互干扰。理想情况下,即使有几十个事务同时运行,每个事务的表现也应如同单独运行一样。

实际上,数据库提供不同的隔离级别,在严格性和性能之间进行权衡。较弱的级别允许某些异常(脏读、幻读)发生,以换取更高的并发性。

这是任何 ACID 面试中内容最丰富的部分,因此接下来的两节课会深入讲解隔离级别和读异常。

为什么隔离性是一个范围

完美隔离(SERIALIZABLE)代价很高,因为它必须阻止所有可能的交错冲突,通常需要锁定事务或中止事务。

因此,SQL 标准定义了四个级别。面试中一个常见陷阱是:候选人以为隔离性只有有或无两种状态。事实并非如此。您需要明确选择所需的隔离程度。

  • READ UNCOMMITTED 最弱
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE 最强
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT SUM(balance) FROM accounts;
-- ... business logic ...
COMMIT;

D = 持久性

持久性意味着事务一旦提交,其更改就能经受崩溃、断电和重启。已提交的事务会保存在稳定存储中。

数据库通过预写日志(WAL)实现这一点:在更新数据文件之前,先将更改写入持久日志。重启时,引擎会重放日志,以恢复那些已经提交但尚未写入主文件的工作。

面试表述:“WAL 保证了持久性;只有在日志记录刷新到磁盘后,提交操作才会返回。”

整合银行转账示例

一次转账会同时体现全部四项属性:

  • 原子性:两次更新要么都生效,要么都不生效。
  • 一致性:CHECK 确保余额不会为负数。
  • 隔离性:并发读取者不会看到只完成了一半的转账。
  • 持久性:COMMIT 之后,新余额能够在崩溃后保留下来。

能够将一个具体示例对应到这四个字母,正是面试中得分的关键。

BEGIN;
UPDATE accounts SET balance = balance - 100
  WHERE id = 1 AND balance >= 100;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

常见追问

面试官经常会进一步探究边界情况。请准备好回答以下问题:

  • “外键保证哪项属性?”一致性。
  • “什么能保护您免受事务执行过程中服务器崩溃的影响?”原子性(回滚未提交的更改)加上持久性(重放已提交的更改)。
  • “隔离性是免费的吗?”不是,更强的隔离性会牺牲并发性。
  • “NoSQL 存储提供 ACID 吗?”许多 NoSQL 存储会用可用性换取 ACID(BASE);请说明这取决于具体引擎。

快速检查

测试您对 ACID 各项属性作用的理解。

回顾:一口气讲清 ACID

现在您已经可以清晰地回答这个问题:

  • 原子性 - 要么全部成功,要么全部失败;部分完成的工作会被回滚。
  • 一致性 - 每次提交都遵守约束,并留下有效状态。
  • 隔离性 - 并发事务不会相互破坏;严格程度可以调整。
  • 持久性 - 已提交的数据能够经受崩溃,并由预写日志提供保障。

将每个字母都对应到它所防止的一种具体故障,您就能从容应对任何并发面试的开场问题。

常见问题解答

「ACID 属性详解」课时是免费的吗?

是的 — 「ACID 属性详解」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 SQL Interview Prep 课程共包含 4 节课。

「ACID 属性详解」这节课中我会学到什么?

结合具体示例学习原子性、一致性、隔离性和持久性。 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 SQL Interview Prep 需要有经验吗?

无需任何先前经验。CoddyKit 上的 SQL Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「ACID 属性详解」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 SQL Interview Prep 课中编写并运行代码吗?

能。每节 SQL Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. ACID 属性详解
  2. 四种隔离级别
  3. 脏读、不可重复读与幻读
  4. 死锁、锁与 MVCC
← 返回 SQL Interview Prep