本文最后更新于 2025-10-16,文章内容可能已经过时。

数据库事务的隔离级别(Isolation Level)是数据库管理系统(DBMS)用来控制并发事务之间相互影响程度的一种机制。它定义了在一个事务中,其他事务对数据的修改在何时可见,以及如何避免常见的并发问题。


一、标准的事务隔离级别(SQL-92 标准)

根据 ANSI/ISO SQL-92 标准,定义了四种标准的事务隔离级别,从低到高依次为:

  1. READ UNCOMMITTED(读未提交)

    • 最低的隔离级别。
    • 允许一个事务读取另一个事务尚未提交的数据。
    • 可能导致的问题:
      • 脏读(Dirty Read):读到了未提交的数据,如果该事务回滚,则读到的数据无效。
      • 不可重复读(Non-Repeatable Read)
      • 幻读(Phantom Read)
  2. READ COMMITTED(读已提交)

    • 保证一个事务只能读取到已经提交的数据。
    • 避免了脏读
    • 但可能出现:
      • 不可重复读:在同一事务中,两次读取同一行数据,结果不同(因为其他事务修改并提交了该行)。
      • 幻读:在同一事务中,两次执行相同查询,返回的行数不同(因为其他事务插入或删除了符合条件的行)。
  3. REPEATABLE READ(可重复读)

    • 保证在同一事务中多次读取同一数据时结果一致。
    • 避免了脏读不可重复读
    • 但某些数据库仍可能出现幻读(取决于实现方式)。
  4. SERIALIZABLE(可串行化)

    • 最高的隔离级别。
    • 所有事务依次执行,如同串行执行一样,完全避免了并发问题。
    • 完全避免了:
      • 脏读
      • 不可重复读
      • 幻读
    • 代价是性能较低,容易发生锁冲突或事务回滚。

⚠️ 注意:不同数据库对这些标准的实现可能略有差异。


二、PostgreSQL 的实际事务隔离级别

PostgreSQL 支持三种事务隔离级别,分别对应 SQL 标准中的后三种,但它通过 多版本并发控制(MVCC) 实现,而不是传统的锁机制,因此行为上有所不同。

PostgreSQL 支持的隔离级别:

  1. READ COMMITTED(默认)

    • 这是 PostgreSQL 的默认隔离级别
    • 在同一个事务中,每次执行 SELECT 查询时,都会看到截至该查询开始时所有已提交事务的最新数据。
    • 行为特点:
      • 避免脏读。
      • 允许不可重复读和幻读。
      • 性能好,适用于大多数场景。
  2. REPEATABLE READ

    • 在此级别下,事务会“冻结”一个数据快照,整个事务期间都基于这个快照读取数据。

    • 因此:

      • 避免脏读。
      • 避免不可重复读。
      • 理论上也避免幻读(但在 PostgreSQL 中,由于 MVCC 的实现,它实际上防止了幻读,但官方文档称其“类似可串行化”,见下文)。
    • ⚠️ 特别注意:PostgreSQL 的 REPEATABLE READ 实际上比标准更严格,它会检测串行化异常。如果检测到冲突,事务将被拒绝并报错:

      ERROR: could not serialize access due to concurrent update

      此时需要应用程序重试事务。

  3. 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 + 快照
SERIALIZABLESSI (MVCC 扩展)

*注:PostgreSQL 的 REPEATABLE READ 通过快照避免幻读,但标准中不保证;而 SERIALIZABLE 是真正防止所有异常。


四、如何设置隔离级别(PostgreSQL 示例)

修改postgresql.conf文件(推荐)

这是最标准的永久修改方式,需要重启PostgreSQL服务才能生效。

步骤:

  1. 找到postgresql.conf文件位置

    • 通常在PostgreSQL数据目录下,例如:/etc/postgresql/<version>/main/postgresql.conf/var/lib/pgsql/data/postgresql.conf
    • 也可以在psql中执行以下命令查找:
    SHOW config_file;
    
  2. 编辑postgresql.conf文件

    • 使用文本编辑器打开该文件
    • 找到default_transaction_isolation参数
    • 将其值修改为所需的隔离级别:
default_transaction_isolation = 'REPEATABLE READ'  # 或 'SERIALIZABLE'
  • 例如,要设置为可重复读:
default_transaction_isolation = 'REPEATABLE READ'
  1. 重启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 READSERIALIZABLE后,应用程序可能需要处理序列化异常(如事务回滚并重试)。这是为了确保数据一致性而付出的代价。

通过这种方式永久修改默认事务隔离级别,可以确保所有新创建的会话都使用你指定的隔离级别,而无需在每个应用程序中单独设置。


五、选择建议

  • 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 技术提供了高效且强一致性的并发控制。