Skip to content

事务的隔离级别有什么

并发场景下的三类问题

  • 脏读 (Dirty Read): 一个事务读取到了另一个事务尚未提交的数据。如果后一个事务回滚,那么第一个事务读取到的就是无效的“脏”数据。
  • 不可重复读 (Non-repeatable Read): 在同一个事务内,多次读取同一行数据,结果却不一致。这是因为在读取间隔内,有其他事务修改了该行数据并提交。
  • 幻读 (Phantom Read): 在同一个事务内,多次执行同样的范围查询,返回的结果集行数不同。这是因为在查询间隔内,有其他事务插入或删除了满足查询条件的数据行,仿佛出现了“幻影”。

四种事务隔离级别

针对上述并发问题,SQL标准提出了四种隔离级别:

1. 读未提交 (Read Uncommitted)

这是最低的隔离级别。在此级别下,一个事务可以看到其他事务尚未提交的变更。

  • 解决的问题: 无,这是隔离级别最低的,无法解决任何并发问题。
  • 可能出现的问题: 脏读、不可重复读、幻读。
  • 优点: 并发性能最高,因为它几乎没有加锁的开销。
  • 缺点: 数据一致性最差,实际应用中很少使用。

2. 读已提交 (Read Committed)

这是大多数数据库系统默认的隔离级别(但MySQL的InnoDB引擎例外)。 在此级别下,一个事务只能读取到已经提交的事务所做的变更。

  • 解决的问题: 脏读。
  • 可能出现的问题: 不可重复读、幻读。
  • 实现方式: 在PostgreSQL等数据库中,一个SELECT查询只能看到在查询开始之前就已经提交的数据。 即使在同一个事务中,两个连续的SELECT查询也可能会看到不同的数据,因为中间可能有其他事务提交了更改。

3. 可重复读 (Repeatable Read)

这是MySQL InnoDB存储引擎的默认隔离级别。 此级别保证在同一个事务中多次读取同一行数据时,结果都是相同的。

  • 解决的问题: 脏读、不可重复读。
  • 可能出现的问题: 幻读。
  • 实现方式:
    • 在非多版本并发控制(MVCC)的数据库中,这通常通过对读取的行加锁直到事务结束来实现,以防止其他事务修改这些行。
    • 在支持MVCC的数据库(如InnoDB)中,事务在启动时会创建一个数据快照(Read View),整个事务期间的所有读取操作都基于这个快照,从而保证了可重复读。 值得注意的是,InnoDB在可重复读级别下,通过多版本并发控制(MVCC)和next-key locking技术,很大程度上避免了幻读现象。

4. 串行化 (Serializable)

这是最高的隔离级别。它强制事务串行执行,即一个接一个地处理,从而避免了所有并发问题。

  • 解决的问题: 脏读、不可重复读、幻读。
  • 可能出现的问题: 无。
  • 实现方式: 通常通过对读取的每一行数据都加上读写锁来实现。当多个事务对同一记录进行读写操作时,如果发生冲突,后访问的事务必须等待前一个事务执行完成。
  • 优点: 提供了最高级别的数据一致性。
  • 缺点: 性能最低,因为并发度大大降低,可能导致大量的超时和锁竞争,一般不推荐在生产环境中使用。