并发事务同时读写时会遇到各种一致性问题,隔离级别就是「在并发与一致性之间选一个平衡点」。理解它,才能正确设计事务和复用数据库的默认行为。

一、并发事务的三种现象

现象含义
脏读读到其他事务未提交的数据
不可重复读同一事务内两次读同一行,结果不同
幻读同一事务内两次范围查询,结果集行数不同

由弱到强,隔离级别就是对这三种现象的「逐步收口」。

二、四种隔离级别

隔离级别脏读不可重复读幻读
READ UNCOMMITTED可能可能可能
READ COMMITTED避免可能可能
REPEATABLE READ避免避免可能
SERIALIZABLE避免避免避免

三、常见数据库的默认值与实现

MySQL(InnoDB)默认是 REPEATABLE READ,但通过 MVCC(多版本并发控制)+ 间隙锁,实际上也避免了幻读。它的实现方式是:

  • MVCC 让普通读(快照读)不加锁,靠版本号实现一致性快照。
  • 对范围查询加间隙锁(gap lock),阻止其他事务插入新行,从而避免幻读。

PostgreSQL 默认是 READ COMMITTED,同样用 MVCC 实现,但普通读不产生间隙锁,在 REPEATABLE READ 下也主要靠快照对付幻读。

Oracle 默认是 READ COMMITTED,且只支持 READ COMMITTED 和 SERIALIZABLE 两种。

四、实际开发怎么选

  1. 默认用数据库默认值即可,绝大多数场景 READ COMMITTED(PG/Oracle)或 REPEATABLE READ(MySQL)都够用。
  2. 需要强一致时用 SERIALIZABLE,但对并发性能影响大,要谨慎评估。
  3. 别用 READ UNCOMMITTED,脏读带来的数据错误很难排查。
  4. 事务要短:隔离级别锁定的资源随事务存活时间越长,冲突概率越高,尽量把事务控制在最小范围。

五、一个容易混淆的点

「不可重复读」和「幻读」的区别在于:不可重复读针对同一行的数据变化,幻读针对结果集行数的变化。MySQL 的 REPEATABLE READ 通过 MVCC 解决了前者,通过间隙锁解决了后者,所以 MySQL 的 RR 实际等价于别的数据库的 SERIALIZABLE 在幻读上的表现。

小结

隔离级别是「并发与一致性」的权衡。理解脏读、不可重复读、幻读三种现象,再对照各数据库的默认值和实现差异,就能为业务选择合适的事务隔离级别,而不是盲目提升或降低。