数据库隔离级别

隔离级别决定了事务之间的可见性规则,直接影响数据库的并发性能和数据一致性。

SQL 标准定义了 4 种隔离级别,从低到高依次为:读未提交→读已提交→可重复读→串行化。隔离级别越高,对并发问题的解决能力越强,但对性能的消耗也越大(因限制了并发操作)。

一、读未提交(Read Uncommitted, RU)

定义 :一个事务可以读取另一个事务 未提交的修改。

解决的问题:无(是最低级别的隔离,几乎不做任何隔离控制)。

存在的问题 :可能出现 脏读、不可重复读、幻读

示例

1、事务 B 执行 "修改数据 X 为 100" 但未提交

2、事务 A 读取 X=100;

3、事务 B 回滚(X 恢复为 50),事务 A 读取的 "100" 是无效的(脏读)。

适用场景:极少使用,仅在对数据一致性要求极低、追求极致并发性能时(如实时监控数据,允许临时脏数据)。

二、读已提交(Read Committed, RC)

定义 :一个事务只能读取另一个事务已提交的修改(未提交的修改不可见)。

解决的问题 :避免 脏读(因只能读已提交的数据)。

存在的问题 :可能出现 不可重复读、幻读

示例

1、事务 A 第一次读取 X=50;

2、事务 B 修改 X 为 100 并提交;

3、事务 A 第二次读取 X=100(与第一次不一致,不可重复读)。

实现原理:通过 "行级锁" 或 "快照读" 实现(如 Oracle 默认用快照读:每个事务读取数据时,获取该数据的 "已提交版本")。

适用场景 :大多数互联网业务(如电商订单、支付场景),平衡了一致性和并发性能,是 Oracle、SQL Server 的默认隔离级别

三、可重复读(Repeatable Read, RR)

定义 :一个事务在执行期间,多次读取同一批数据的结果始终一致(不受其他事务提交的修改影响)。

解决的问题 :避免脏读、不可重复读

存在的问题 :可能出现幻读(因无法限制其他事务新增 / 删除符合条件的记录)。

示例

1、事务 A 第一次查询 "年龄> 18 的用户",返回 10 条;

2、事务 B 新增 1 条 "年龄 = 20" 的用户并提交;

3、事务 A 再次查询 "年龄> 18 的用户",返回 11 条(记录数变化,幻读)。

实现原理 :通过 "多版本并发控制(MVCC)" 实现(每个事务启动时生成一个 "数据快照",后续读取基于该快照,不受其他事务提交的修改影响)。

特殊说明 :MySQL 的 InnoDB 引擎对 RR 做了增强,通过 "间隙锁(Gap Lock)" 避免了部分幻读场景(但并非完全解决,极端情况仍可能出现),因此 InnoDB 的 RR 实际隔离性略高于标准定义。

适用场景 :对数据一致性要求较高的业务(如金融交易、库存管理),是 MySQL InnoDB 的默认隔离级别

四、串行化(Serializable, S)

定义 :所有事务 "串行执行"(即一个接一个执行,不允许并发操作同一批数据)。

解决的问题 :避免 脏读、不可重复读、幻读(是最高级别的隔离,完全保证数据一致性)。

存在的问题:并发性能极差(因本质是 "单线程" 执行,会导致大量事务等待)。

实现原理 :通过 "表级锁 " 或 "范围锁" 强制事务串行化(如事务 A 操作某范围数据时,其他事务对该范围的读写均被阻塞)。

示例

1、事务 A 执行 "查询年龄> 18 的用户" 并准备修改;

2、事务 B 尝试新增 "年龄 = 20" 的用户时,会被阻塞,直到事务 A 完成并释放锁;

3、因此事务 A 两次查询的结果完全一致,无幻读。

适用场景:仅在对数据一致性要求极高、并发量极低的场景(如银行核心交易的对账操作,不允许任何并发不一致)。

隔离级别对比

隔离级别 脏读 不可重复读 幻读 并发性能 典型数据库默认值
读未提交(RU) 可能 可能 可能 最高 几乎无数据库默认
读已提交(RC) 不可能 可能 可能 较高 Oracle、SQL Server
可重复读(RR) 不可能 不可能 可能 中等 MySQL InnoDB
串行化(S) 不可能 不可能 不可能 最低 无数据库默认

不可重复读与脏读的区别

  • 脏读( Dirty Read**)** :读取到其他事务 未提交的数据;
  • 不可重复读( Non-repeatable Read**)** :读取到其他事务 已提交修改

不可重复读与幻读的区别

  • 不可重复读( Non-repeatable Read**)** :针对 已存在 数据的 修改
  • 幻读( Phantom Read**)** :针对 新增或删除的数据行。

人活一世,谋生之道,立世之途,为人之智,尽在书中。-- 烟沙九洲