脏读、幻读、不可重复读产生的原因及解决方案

一、脏读(Dirty Read)

产生原因
  • 直接原因:事务 A 读取了事务 B 未提交的修改,而事务 B 后续可能回滚(Rollback),导致事务 A 读取到无效数据。

  • 根本原因:事务隔离级别设置为 Read Uncommitted(读未提交),允许事务读取其他未提交事务的中间状态。

场景示例
  1. 事务 B 更新某行数据(但未提交)。

  2. 事务 A 读取该行数据(未提交的脏数据)。

  3. 事务 B 回滚,数据恢复原值。

  4. 事务 A 后续操作基于脏数据,导致逻辑错误。


二、不可重复读(Non-Repeatable Read)

产生原因
  • 直接原因:事务 A 多次读取同一数据,期间事务 B 对该数据进行了 修改并提交,导致事务 A 前后读取结果不一致。

  • 根本原因:事务隔离级别为 Read Committed(读已提交),允许其他事务在两次读取之间提交修改。

场景示例
  1. 事务 A 第一次读取某行数据,值为 100。

  2. 事务 B 更新该行数据为 200 并提交。

  3. 事务 A 第二次读取同一行数据,值为 200。

  4. 事务 A 在同一事务中两次读取结果不一致,破坏事务的隔离性。


三、幻读(Phantom Read)

产生原因
  • 直接原因:事务 A 多次执行同一范围查询,期间事务 B 插入或删除了符合该查询条件的记录并提交,导致事务 A 前后读取的结果集大小不一致。

  • 根本原因:事务隔离级别为 Repeatable Read(可重复读)时,MVCC 的快照读可以避免幻读,但 当前读(如 SELECT ... FOR UPDATE)可能因未锁定范围而出现幻读。

    • InnoDB 的优化:通过 Next-Key Lock(记录锁 + 间隙锁)锁定索引范围,防止其他事务插入数据。

场景示例
  1. 事务 A 查询年龄在 20-30 岁的用户,返回 5 条记录。

  2. 事务 B 插入一条年龄为 25 岁的新用户并提交。

  3. 事务 A 再次查询同一范围,返回 6 条记录。

  4. 事务 A 发现“凭空出现”的新数据,如同幻觉(幻读)。

  5. 四、三者的核心区别

    问题类型操作类型数据变化形式隔离级别场景
    脏读读取未提交的数据单行数据的未提交修改Read Uncommitted
    不可重复读读取已提交的数据单行数据的已提交修改Read Committed
    幻读范围查询结果集中记录的增删Repeatable Read(未完全解决)

五、数据库如何解决这些问题?

  1. 脏读:提升隔离级别至 Read Committed(读已提交),确保只读取已提交的数据。

  2. 不可重复读:提升隔离级别至 Repeatable Read(可重复读),通过 MVCC 的快照保证事务内一致性。

  3. 幻读:在 Repeatable Read (可重复读)下,通过 Next-Key Lock(记录锁+间隙锁) 锁定索引范围;或提升至 Serializable(串行化) 完全串行化执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值