四种隔离级别
从读未提交到可串行化,了解每种级别允许的行为。
四种隔离级别 是 CoddyKit 上的免费 SQL Interview Prep 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Interview Prep 课程共包含 4 节课。
问题背后的问题
当面试官要求您“说出四个隔离级别”时,真正考查的是您能否解释其中的权衡:隔离性越强,异常越少,但并发性越低。
SQL 标准定义了四个级别,按从弱到强排列:
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
每个级别都会允许或禁止一组特定的读异常。本课讲解这些级别,下一课将详细介绍这些异常。
设置隔离级别
您可以按事务或按会话设置隔离级别。不同引擎使用的语法几乎相同。
如果您不设置隔离级别,每个数据库都会使用一个默认值。了解默认值是面试中的常见问题,因此我们会在最后介绍它们。
-- Per transaction (standard SQL)
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- ... statements ...
COMMIT;
-- Per session
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;级别 1:READ UNCOMMITTED
READ UNCOMMITTED 是最弱的级别。事务可以读取另一个事务已经修改但尚未提交的数据行。这些数据被称为脏读。
如果另一个事务随后回滚,您读到的就是从未正式存在过的数据。对于任何必须保证正确性的操作来说,这都很危险。
注意:Postgres 会将 READ UNCOMMITTED 视为 READ COMMITTED,因此实际上永远不会发生脏读。SQL Server 和 MySQL 则会遵守这一设置。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN;
-- may see another transaction's uncommitted (dirty) rows
SELECT balance FROM accounts WHERE id = 1;
COMMIT;级别 2:READ COMMITTED
READ COMMITTED 保证您读取到的始终是已经提交的数据,不会发生脏读。
但是,每条语句看到的都是最新的已提交快照。如果您在一个事务中两次执行同一个查询,中间可能有另一个已提交的事务改变结果。这种异常称为不可重复读。
这是Postgres、Oracle 和 SQL Server 的默认级别,对于大多数应用来说,它是一个合理的平衡。
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
SELECT balance FROM accounts WHERE id = 1; -- returns 500
-- another transaction commits an update to id = 1
SELECT balance FROM accounts WHERE id = 1; -- may now return 700
COMMIT;级别 3:REPEATABLE READ
REPEATABLE READ 确保您在同一个事务中两次读取同一行时,两次得到的值相同。它会在事务开始时获取一个一致的快照。
它可以防止脏读和不可重复读。按照标准,它仍然允许幻读:重新查询时,可能出现与您的 WHERE 子句匹配的新数据行。
重要:这是 MySQL/InnoDB 的默认级别,而且 InnoDB 的实现还会通过间隙锁和记录锁阻止大多数幻读。
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
SELECT balance FROM accounts WHERE id = 1; -- 500
-- another transaction commits a change to id = 1
SELECT balance FROM accounts WHERE id = 1; -- still 500 in this txn
COMMIT;级别 4:SERIALIZABLE
SERIALIZABLE 是最严格的级别。数据库保证并发运行事务所得的结果,与按照某种串行顺序一个接一个地运行这些事务所得的结果相同。
它可以防止脏读、不可重复读和幻读。代价是需要更多锁,或者在 Postgres 中因序列化失败而中止事务,您必须进行重试。
面试表述:“SERIALIZABLE 让人感觉每个事务都是单独运行的,但代价是并发性降低,并且可能需要重试。”
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT SUM(balance) FROM accounts;
INSERT INTO audit (total) VALUES (...);
COMMIT; -- may raise a serialization_failure you retry异常矩阵
最值得记住的一点,是每个级别允许哪种异常。“是”表示该异常可能发生。
- READ UNCOMMITTED:脏读=是、不可重复读=是、幻读=是
- READ COMMITTED:脏读=否、不可重复读=是、幻读=是
- REPEATABLE READ:脏读=否、不可重复读=否、幻读=是(按照标准)
- SERIALIZABLE:脏读=否、不可重复读=否、幻读=否
每提高一级,就会多禁止一种异常。这种递进关系就是完整答案。
标准与实际实现
一个体现资深水平的区别是:SQL 标准根据各级别必须防止哪些异常来定义级别,而不是规定具体实现方式。实际引擎通常会防止更多异常。
- Postgres REPEATABLE READ 使用快照隔离,也会阻止幻读,但仍可能发生写偏斜。
- MySQL/InnoDB REPEATABLE READ 使用间隙锁和记录锁阻止幻读。
- Postgres SERIALIZABLE 使用 SSI(可串行化快照隔离),在发生冲突时中止事务,而不是依赖大量锁。
提到这些内容可以表明,您知道标准只是最低要求,并不代表实际行为的全部细节。
各引擎的默认级别
默认值经常会被问到。请牢记:
- PostgreSQL: READ COMMITTED
- Oracle: READ COMMITTED(永远不会发生脏读)
- SQL Server: READ COMMITTED
- MySQL(InnoDB): REPEATABLE READ
MySQL 的特殊之处是面试中很受欢迎的陷阱。如果有人问“默认隔离级别是什么?”,请始终先确认具体引擎。
在实践中选择级别
应该如何决定?可以从风险与吞吐量的角度进行权衡。
- 典型的 OLTP 场景使用 READ COMMITTED;它速度快,并且可以避免脏读。
- 当事务会多次读取相同数据且数据必须保持稳定时,使用 REPEATABLE READ(例如报表和多步骤计算)。
- 对于任何异常都不可接受、对正确性要求极高的逻辑,使用 SERIALIZABLE,并为事务中止设计重试逻辑。
在生产环境中几乎不要使用 READ UNCOMMITTED。
常见追问
列出这些级别后,面试官通常会快速追问。请准备好简洁明确的答案:
- “哪个级别可以防止脏读,但允许不可重复读?”READ COMMITTED。
- “按照标准,REPEATABLE READ 仍然允许的唯一异常是什么?”幻读。
- “为什么不总是使用 SERIALIZABLE?”它会降低并发性,并且可能因序列化失败而迫使事务重试。
- “级别越高,代价越大吗?”是的,代价可能体现为锁开销,或者中止并重试的开销。
能够立即回答这些问题,说明您真正掌握了这条级别阶梯,而不是死记硬背。
快速检查
下面考查的是最常被测试的默认级别知识之一。
回顾:四个级别,一项权衡
四个隔离级别构成一条从弱到强的阶梯:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE。每提高一级,就会多禁止一种异常(脏读、不可重复读、幻读),代价是并发性降低。
请记住默认值(除了 MySQL 使用 REPEATABLE READ 外,其他地方都是 READ COMMITTED),并注意实际引擎通常会防止比标准要求更多的异常。接下来,我们将研究这些级别旨在阻止的三种读异常。
常见问题解答
「四种隔离级别」课时是免费的吗?
是的 — 「四种隔离级别」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 SQL Interview Prep 课程共包含 4 节课。
「四种隔离级别」这节课中我会学到什么?
从读未提交到可串行化,了解每种级别允许的行为。 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Interview Prep 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「四种隔离级别」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Interview Prep 课中编写并运行代码吗?
能。每节 SQL Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。