数据库事务:脏读、不可重复读、幻读

相关文章:数据库的4种事务隔离级别

脏读(Dirty read)

脏读发生在 一个事务读取了被另一个事务改写但尚未提交的数据时。
如果这些改变在稍后被回滚了,那么第一个事务读取的数据就会是无效的。

执行流程,如下图:

  1. 时间1,开启T1事务
  2. 时间2,T1事务中执行 insert 插入。关键:此时还未提交
  3. 时间3,开启T2事务
  4. 时间4. T2事务中执行 select 查询。关键:此时会查询到 T1事务 插入但未提交 的数据
  5. 时间5,T2事务结束
  6. 时间6,T1事务中发生错误,T1事务回滚,insert 插入的数据并 没有添加到数据库中

错误:T1事务中,添加数据失败,但 T2事务中却 查询出该条记录

代码验证:数据库事务:验证隔离级别-脏读

不可重复读(Nonrepeatable read)

T1事务执行 多次查询,T1 执行第1次查询,然后并发事务 T2 执行修改,当 T1事务 再次查询时,就会查询到 T2 事务已经 修改的记录。

违背的事务一致性,即:T1 事务中,多次查询的结果应该一致

不可重复读 重点在 修改

执行流程,如下图:

  1. 时间1,开启T1事务
  2. 时间2,T1事务中执行 select 查询
  3. 时间3,开启T2事务
  4. 时间4. T2事务中执行 update 修改
  5. 时间5,T2事务提交,即:结束
  6. 时间6,T1事务中执行 select 查询,能够查询到 T2事务修改的数据

错误: T1事务中,执行 多次查询,第2次查询,查询到 T2事务 修改的数据,与第1次查询的数据不一致。违反ACID中的数据一致性,一个事务中,多次查询,查询结果应该一致

代码验证:数据库事务:验证隔离级别-不可重复读

幻读(Phantom reads)

幻读和不可重复读相似

T1事务执行 多次查询,执行第1次查询,然后并发事务T2 删除或者插入数据,当 T1事务 再次查询时,第二次结果 与 第一次查询结果不一致

违背的事务一致性,即:T1 事务中,多次查询的结果应该一致

幻读 重点在 新增 或 删除

执行流程,如下图:

  1. 时间1,开启T1事务
  2. 时间2,T1事务中执行 select 查询
  3. 时间3,开启T2事务
  4. 时间4. T2事务中执行 delete 删除
  5. 时间5,T2事务提交,即:结束
  6. 时间6,T1事务中执行 select 查询,不会查询 到 T2事务删除的数据

错误: T1事务中,执行 多次查询,第2次查询,查询到 T2事务 修改的数据,与第1次查询的数据不一致。违反ACID中的数据一致性,一个事务中,多次查询,查询结果应该一致

代码验证:数据库事务:验证隔离级别-幻读

快照读

普通查询语句是快照读,读取的是当时的记录

举例解释 快照: 中国人口众多,普查人口数量并 汇总期间,又有人口变动,将永远无法统计出人口。
所以为了便于统计,只统计 2023年12月31日 的人口数量,该日期之后的人口变动,不统计在内。

2023年12月31日 的人口数量就相当于 快照

当前读

当前读就是读取当前的数据,如:增、删、改语句,带有 for update 的查询语句,如下:

select * from ....where ... for update

触发幻读

如果事务中都是用 快照读,那么不会产生幻读

快照读 和 当前读 一起使用的时候才会产生幻读

参考:
https://blog.csdn.net/nandao158/article/details/116007366


原文出处:/show_1IX9gVCVzZP.html