脏读(Dirty Read)
定义
脏读是指一个事务可以读取到另一个事务尚未提交的数据变更。由于这些数据变更可能被回滚,因此读取到的数据可能是无效的或不一致的。
产生原因
脏读通常发生在数据库隔离级别设置为”读未提交”(Read Uncommitted)时。
具体表现
- 事务A修改了某条记录但尚未提交
- 事务B读取了事务A修改后的记录
- 如果事务A最终回滚,那么事务B读取到的就是无效数据
解决方案
- 提高事务隔离级别至”读已提交”或更高
- 在数据库层面设置适当的锁机制
不可重复读(Non-repeatable Read)
定义
不可重复读是指在同一事务内,由于其他并发事务的修改操作导致该事务前后两次读取同一数据时结果不一致的现象。
详细示例
- 事务A第一次查询:返回结果1000
- 事务B执行并提交:UPDATE account SET balance = 800
- 事务A再次查询:返回结果800
此时事务A发现两次读取结果不一致。
解决方案
- 提高事务隔离级别到REPEATABLE READ或以上
- 使用悲观锁(SELECT FOR UPDATE)
- 在应用层实现乐观并发控制
重复读(Repeatable Read)
基本概念
重复读是数据库事务隔离级别 REPEATABLE READ 的主要特性,确保在同一事务内多次读取相同数据时结果保持一致。
核心特性
- 防止不可重复读:通过多版本并发控制(MVCC)技术
- 基于快照:基于事务开始时创建的数据快照
解决的问题
- 脏读问题
- 不可重复读问题
幻读(Phantom Read)
定义
幻读指的是在同一个事务内,由于其他并发事务的插入或删除操作,导致前后两次相同的查询返回不同的结果集。
具体表现
- 事务A第一次查询返回N条记录
- 事务B在该范围内插入了新数据并提交
- 事务A再次执行相同查询,返回N+1条记录
与不可重复读的区别
- 不可重复读:针对已存在行的数据被修改
- 幻读:针对新增或删除的行导致结果集变化
解决方案
- 提升隔离级别到串行化(SERIALIZABLE)
- 使用间隙锁(Gap Lock)或Next-Key Lock
- 使用悲观锁(如SELECT…FOR UPDATE)
总结
| 问题 | 发生隔离级别 | 解决方案 |
|---|---|---|
| 脏读 | READ UNCOMMITTED | 提高隔离级别 |
| 不可重复读 | READ COMMITTED | 使用REPEATABLE READ |
| 幻读 | REPEATABLE READ | 使用SERIALIZABLE |