并发事务引入的问题:幻读、不可重复读、脏读
总结
整理了并发 事务 时会出现的幻读、不可重复读、脏读问题。
详情
概念
现象 | 定义简述 |
---|---|
幻读(Phantom Read) | 同一个事务内多次查询某一范围的记录,结果数量变化,出现“幻行”。 |
不可重复读(Non-Repeatable Read) | 同一个事务内多次读取同一数据,结果不一致。 |
脏读(Dirty Read) | 一个事务读取了另一个事务未提交的数据。 |
幻读举例说明
事务 A 在读取某个范围内的记录时,事务 B 又在该范围内插入了新的记录,事务 A 再次读取该范围的记录时,会产生幻行(Phantom Row)。
假设有 A 和 B 这两个事务同时在处理:
- 事务 A 查询符合要求的记录,发现共有 3 条;
- 事务 B 插入了 2 条新纪录并提交事务;
- 事务 A 再次查询记录,此时查询到的记录数有 5 条
前后两次记录数不一致,这就是幻读。
不可重复读举例说明
假设有 A 和 B 这两个事务同时在处理:
- 事务 A 查询账户余额,然后继续执行代码;
- 事务 B 更新了账户余额并提交事务;
- 事务 A 再次查询账户余额,此时账户余额变了。
前后两次读取的数据不一致,这种现象就被称为不可重复读。
脏读举例说明
假设有 A 和 B 这两个事务同时在处理:
- 事务 A 更新账户余额,但还没有提交事务
- 事务 B 读取账户余额,
事务 B 读取的是事务 A 修改后未提交事务的数据,发生了脏读。
事务 A 还没提交事务,随时可能发生回滚操作,如果事务 A 发生了回滚,那么事务 B 读取的数据就是不正确的。
对比
对比维度 | 幻读 | 不可重复读 | 脏读 |
---|---|---|---|
发生对象 | 查询结果集(多行集合) | 数据项(某一行某个字段) | 数据项(如某一行某个字段) |
操作类型 | 插入或删除导致记录数变化 | 读取已提交的修改 | 读取未提交的修改 |
是否涉及新增/删除记录 | ✅ | ❌ | ❌ |
是否违反一致性 | 影响一致性(逻辑错误) | 部分违反一致性 | 严重违反一致性(读到无效数据) |
举例 | A 两次查询记录,B 插入了两条 | A 两次查余额,B 中间更新了它 | B 读 A 未提交的余额修改 |
严重程度 | 较轻 | 中等 | 最严重 |
三个现象的严重性排序如下:脏读>不可重复读>幻读