数据库事务隔离级别、PostgreSQL实际有哪几种事务隔离级别
本文最后更新于 2025-10-16,文章内容可能已经过时。
数据库事务的隔离级别(Isolation Level)是数据库管理系统(DBMS)用来控制并发事务之间相互影响程度的一种机制。它定义了在一个事务中,其他事务对数据的修改在何时可见,以及如何避免常见的并发问题。
一、标准的事务隔离级别(SQL-92 标准)
根据 ANSI/ISO SQL-92 标准,定义了四种标准的事务隔离级别,从低到高依次为:
-
READ UNCOMMITTED(读未提交)
- 最低的隔离级别。
- 允许一个事务读取另一个事务尚未提交的数据。
- 可能导致的问题:
- 脏读(Dirty Read):读到了未提交的数据,如果该事务回滚,则读到的数据无效。
- 不可重复读(Non-Repeatable Read)
- 幻读(Phantom Read)
-
READ COMMITTED(读已提交)
- 保证一个事务只能读取到已经提交的数据。
- 避免了脏读。
- 但可能出现:
- 不可重复读:在同一事务中,两次读取同一行数据,结果不同(因为其他事务修改并提交了该行)。
- 幻读:在同一事务中,两次执行相同查询,返回的行数不同(因为其他事务插入或删除了符合条件的行)。
-
REPEATABLE READ(可重复读)
- 保证在同一事务中多次读取同一数据时结果一致。
- 避免了脏读和不可重复读。
- 但某些数据库仍可能出现幻读(取决于实现方式)。
-
SERIALIZABLE(可串行化)
- 最高的隔离级别。
- 所有事务依次执行,如同串行执行一样,完全避免了并发问题。
- 完全避免了:
- 脏读
- 不可重复读
- 幻读
- 代价是性能较低,容易发生锁冲突或事务回滚。
⚠️ 注意:不同数据库对这些标准的实现可能略有差异。
二、PostgreSQL 的实际事务隔离级别
PostgreSQL 支持三种事务隔离级别,分别对应 SQL 标准中的后三种,但它通过 多版本并发控制(MVCC) 实现,而不是传统的锁机制,因此行为上有所不同。
PostgreSQL 支持的隔离级别:
-
READ COMMITTED(默认)
- 这是 PostgreSQL 的默认隔离级别。
- 在同一个事务中,每次执行
SELECT查询时,都会看到截至该查询开始时所有已提交事务的最新数据。 - 行为特点:
- 避免脏读。
- 允许不可重复读和幻读。
- 性能好,适用于大多数场景。
-
REPEATABLE READ
-
在此级别下,事务会“冻结”一个数据快照,整个事务期间都基于这个快照读取数据。
-
因此:
- 避免脏读。
- 避免不可重复读。
- 理论上也避免幻读(但在 PostgreSQL 中,由于 MVCC 的实现,它实际上防止了幻读,但官方文档称其“类似可串行化”,见下文)。
-
⚠️ 特别注意:PostgreSQL 的
REPEATABLE READ实际上比标准更严格,它会检测串行化异常。如果检测到冲突,事务将被拒绝并报错:ERROR: could not serialize access due to concurrent update此时需要应用程序重试事务。
-
-
SERIALIZABLE
-
PostgreSQL 从 9.1 版本开始支持真正的
SERIALIZABLE隔离级别。 -
使用一种称为 Serializable Snapshot Isolation (SSI) 的算法,基于 MVCC 实现。
-
提供最高级别的隔离,确保事务并发执行的结果等价于某种串行顺序。
-
如果系统检测到可能导致不一致的并发操作,会抛出错误:
ERROR: could not serialize access due to read/write dependencies应用程序必须捕获该错误并重试事务。
-
❗ PostgreSQL 不支持
READ UNCOMMITTED隔离级别。即使你显式设置
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;,PostgreSQL 也会将其当作READ COMMITTED处理。这是因为在 MVCC 模型下,根本不会读取未提交的数据,所以“读未提交”没有意义。
三、总结对比表
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | PostgreSQL 支持 | 实现机制 |
|---|---|---|---|---|---|
| READ UNCOMMITTED | ✅ | ✅ | ✅ | ❌(视为 RC) | — |
| READ COMMITTED | ❌ | ✅ | ✅ | ✅(默认) | MVCC |
| REPEATABLE READ | ❌ | ❌ | ❌* | ✅ | MVCC + 快照 |
| SERIALIZABLE | ❌ | ❌ | ❌ | ✅ | SSI (MVCC 扩展) |
*注:PostgreSQL 的 REPEATABLE READ 通过快照避免幻读,但标准中不保证;而 SERIALIZABLE 是真正防止所有异常。
四、如何设置隔离级别(PostgreSQL 示例)
修改postgresql.conf文件(推荐)
这是最标准的永久修改方式,需要重启PostgreSQL服务才能生效。
步骤:
-
找到postgresql.conf文件位置:
- 通常在PostgreSQL数据目录下,例如:
/etc/postgresql/<version>/main/postgresql.conf或/var/lib/pgsql/data/postgresql.conf - 也可以在psql中执行以下命令查找:
SHOW config_file; - 通常在PostgreSQL数据目录下,例如:
-
编辑postgresql.conf文件:
- 使用文本编辑器打开该文件
- 找到
default_transaction_isolation参数 - 将其值修改为所需的隔离级别:
default_transaction_isolation = 'REPEATABLE READ' # 或 'SERIALIZABLE'
- 例如,要设置为可重复读:
default_transaction_isolation = 'REPEATABLE READ'
- 重启PostgreSQL服务:
- 不同系统重启命令不同:
# Ubuntu/Debian
sudo systemctl restart postgresql
# CentOS/RHEL
sudo systemctl restart postgresql-<version>
# 或使用pg_ctl
sudo pg_ctl restart -D /path/to/data/directory
⚠️ 注意:在设置为
REPEATABLE READ或SERIALIZABLE后,应用程序可能需要处理序列化异常(如事务回滚并重试)。这是为了确保数据一致性而付出的代价。
通过这种方式永久修改默认事务隔离级别,可以确保所有新创建的会话都使用你指定的隔离级别,而无需在每个应用程序中单独设置。
五、选择建议
- READ COMMITTED:适用于大多数应用,性能好,数据一致性要求不极端。
- REPEATABLE READ:需要在事务中多次读取一致数据(如报表生成),但要处理可能的序列化异常。
- SERIALIZABLE:对数据一致性要求极高,愿意接受重试逻辑来换取强一致性。
结论
- SQL 标准定义了 4 种隔离级别:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE。
- PostgreSQL 实际支持 3 种:READ COMMITTED、REPEATABLE READ、SERIALIZABLE。
- 它不支持 READ UNCOMMITTED,且通过 MVCC 和 SSI 技术提供了高效且强一致性的并发控制。
- 感谢你赐予我前进的力量

