没封箱的包裹,别人看得见吗?
上期讲了事务:把几步操作装进一个包裹,封好箱(提交)才算数。这期讲同一时间有很多笔事务在跑时,彼此能看到对方多少。
1. 三种「读到不该读的」问题
- 脏读:读到了别的事务还没提交的数据。1
- 不可重复读:同一事务里把同一行读两遍,结果不一样,因为中间被别的事务修改并提交了。1
- 幻读:同一事务里把同一个条件查询跑两遍,符合条件的行变多或变少了,因为中间别的事务刚提交了新数据。1
2. 隔离级别:标准定义的四档
SQL 标准定义了四个隔离级别。1
| 级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交(READ UNCOMMITTED) | 可能 | 可能 | 可能 |
| 读已提交(READ COMMITTED) | 不会 | 可能 | 可能 |
| 可重复读(REPEATABLE READ) | 不会 | 不会 | 可能 |
| 可串行化(SERIALIZABLE) | 不会 | 不会 | 不会 |
3. 各家默认不一样
- MySQL 的 InnoDB 默认可重复读。2
- PostgreSQL 默认读已提交。1 PostgreSQL 里的「读未提交」实际表现和读已提交一样,也就是不会脏读。1
- SQL Server 默认读已提交。3
4. MySQL 的可重复读到底有没有幻读?
这个问题不能用一句话回答,要分情况看手册原文:
- 普通
SELECT读的是事务里第一次读时建立的快照,同一事务里重复读,看不到别人后来提交的改动;但自己在这个事务里改过的数据,会看到改后的样子。2 - 加锁读、
UPDATE、DELETE时,InnoDB 用 next-key 锁(行锁加间隙锁)防止幻读:“To prevent phantoms, InnoDB uses an algorithm called next-key locking that combines index-row locking with gap locking.”4 - 但快照只管
SELECT,不一定管修改语句:别的事务刚提交的行,你查不到,你的UPDATE或DELETE却可能改到它。5
PostgreSQL 的可重复读则明确不允许幻读。1
5. 代价
- 用加锁的方式实现时,别的事务有时得排队等对方结束。6
- 在较高的级别下,事务可能因为冲突而失败,应用程序要准备好重试,相当于整单重来。1
- 微软的文档还说,级别越高,并发问题越少,但要消耗更多资源,事务之间也更容易互相阻塞。6 这一说法目前只找到微软一家来源。
Footnotes
-
PostgreSQL 18 文档 13.2 Transaction Isolation https://www.postgresql.org/docs/18/transaction-iso.html ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
MySQL 8.4 手册 17.7.2.1 Transaction Isolation Levels(2026-10 生成)https://dev.mysql.com/doc/refman/8.4/en/innodb-transaction-isolation-levels.html ↩ ↩2
-
Microsoft Learn:SET TRANSACTION ISOLATION LEVEL(2025-09-26)https://learn.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-ver17 ↩
-
MySQL 8.4 手册 17.7.4 Phantom Rows(2026-10 生成)https://dev.mysql.com/doc/refman/8.4/en/innodb-next-key-locking.html ↩
-
MySQL 8.4 手册 17.7.2.3 Consistent Nonlocking Reads(2026-10 生成)https://dev.mysql.com/doc/refman/8.4/en/innodb-consistent-read.html ↩
-
Microsoft Learn:Transaction Locking and Row Versioning Guide(2026-04-22)https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-transaction-locking-and-row-versioning-guide?view=sql-server-ver17 ↩ ↩2
幕后
这部片子完全由代码生成。
系列 · 数据库第 3/6 期