脏读、脏写、不可重复读、幻读的概念

一般对于我们的业务系统去访问数据库而言,它往往是多个线程并发执行多个事务的,对于数据库而言,它会有多个事务同时执行,可能这多个事务还会同时更新和查询同一条数据,所以这里会产生一些问题。

脏写

脏写:有两个事务,事务 A 和事务 B 同时在更新一条数据,原先数据库中的值为NULL。事务 A 先把它更新为 A 值,事务 B 紧接着就把它更新为 B 值。因为事务B是后更新的,所以数据库中最后会保存B值。但此时,事务A回滚了操作,直接就会把那行数据的值更新回 NULL 值。

此时事务 B 一看,为什么我更新的 B 值没了?因为事务 A 把数据值回滚成 NULL 了,结果我更新的 B 值也不见 了。所以对于事务 B 看到的场景而言,就是自己明明更新了,结果值却没了,这就是脏写。

所谓脏写,就是我刚才明明写了一个数据值,结果过了一会却没了。而它的本质就是事务 B 去修改了事务 A 修改过的值,但是此时事务 A 还没提交,所以事务 A 随时会回滚,导致事务 B 修改的值也没了。

脏读

假设事务 A 更新了一行数据的值为 A 值,此时事务 B 去查询了一下这行数据的值,看到的值是 A 值。接着,事务 B 拿着刚才查询到的 A 值做各种业务处理。但是此时事务 A 突然回滚了事务,导致它刚才更新的A 值没了,此时那行数据的值回滚为 NULL 值。然后事务 B 再次查询那行数据的值,看到的居然是 NULL 值。

这就是脏读。它的本质是事务 B 能去查询事务 A 还没提交的事务 A ,所以事务 A 随时会回滚导,致事务 B 再次查询就读不到刚才事务 A 修改的数据了,这就是脏读。

无论是脏写还是脏读,都是因为一个事务去更新或者查询了另外一个还没提交的事务更新过的数据。因为另外一个事务还没提交,所以它随时可能会回滚,那么必然导致写入或查询的数据就没了,这就是脏写和脏读两种场景。

不可重复读

假设我们有一个事务 A 开启了,在这个事务 A 里会多次对一条数据进行查询。另外有两个事务:事务 B、事务 C,他们两都是对这条数据进行更新的。然后我们假设一个前提,就是比如说事务 B 更新之后,如果还没提交,那么事务 A 是读不到的,必须要事务 B 提交之后,它修改的值才能被事务 A 读取到,其实这种情况下,就是我们首先避免了脏读的发生。

假设缓存页里一条数据原来的值是 A 值,此时事务 A 开启之后,第一次查询这条数据,读取到的就是 A 值。
接着事务 B 更新了那行数据的值为 B 值并且提交,此时事务 A 还没提交,它在事务执行期间第二次查询数据,此时查到的是事务 B 修改过的值,B 值,因为事务 B 已经提交了,所以事务 A 是可以读到的。紧接着事务 C 再次更新数据为 C 值,并且提交事务,此时在事务 A 还没提交的情况下,第三次查询数据,查到的值为 C 值。

明显事务A每次查询到的值都是不重复的。因为事务 B 和事务 C 一旦更新值并且提交了,事务 A 会读到别的值,所以此时这行数据的值是不可重复读的。

幻读

事务 A,先执行一条查询语句,如 SELECT * FROM table WHERE id > 10。它一开始查询出来了 10 条数据。这时,事务 B往表里插了几条数据,而且事务 B 还提交了,此时多了表中几行数据。
接着事务 A 继续执行同样的查询语句,发现两次查询的结果是不一样的。这就是幻读。

脏写、脏读、不可重复读、幻读,都是因为业务系统会多线程并发执行,每个线程可能都会开启一个事务,每个事务都会执行增删改查操作。然后数据库会并发执行多个事务,多个事务可能会并发地对缓存页里的同一批数据进行增删改查操作,于是这个并发增删改查同一批数据的问题,可能就会导致我们说的脏写、脏读、不可重复读、幻读这些问题。

所以这些问题的本质,都是数据库的多事务并发问题,那么为了解决多事务并发问题,数据库才设计了事务隔离机制、MVCC 多版本隔离机制、锁机制,用一整套机制来解决多事务并发问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值