多个事物并发增删改查数据,为什么会有脏读脏写问题?

多个线程并发执行多个事物
image.png
多个事物要对缓存页 里面的同一条数据进行更新或者查询,会产生哪些操作?
实际上会涉及到:脏写、脏读、不可重复读、幻读 四种问题

脏写

image.pngimage.png
事物A与事物B同时更新一条数据,事物A把它更新为A值,紧接着事物B把他更新为B值,此时事物A突然回滚,那条数据值更新回之前的值,此时事物B更新的B值也没了,

本质:
事物B去修改了事物A修改过的值,但是事物A还没提交,此时事物A进行回滚,导致事物B修改的值也没了

脏读

image.pngimage.png
事物A更新了一行数据值为A值,此时事物B去查询一下该行数据值,但是事物A突然回滚,导致更新的A值也没了编程NULL,事物B紧接着再次查询哪行数据的值,此时是NULL值

本质:
事物B去查询事物A修改过的数据,但是此时事物A未提交,所以事物A回滚导致事务B再次查询就读不到刚才事物A修改的数据了

事物B读到了事物A修改过还没提交的数据,此时事物A一旦回滚、事物B再次读就读不到了,此时发生脏读

脏读、脏写小结

无论是脏读 脏写,都是因为一个事物去更新或者查询了另外一个还没提交的事物更新过的数据,
因为另外一个事物还没提交,所以他随时有可能反悔回滚,那么必然导致你更新的数据就没了,或者你之前查到的数据就没了,这就是脏写和脏读的坑爹场景

不可重复读(当前读)

image.png
image.pngimage.png
事物A,事物B,事物C
1、事物A 开启事物 读取 一条数据,
2、此时事物B 对该数据进行修改并提交
3、事物A 再次读取该数据(发现值变了)
4、此时事物C 对该数据进行修改并提交
5、事物A 再次读取该数据(发现值变了)
这种情况 叫不可重复读(一次事物内多次读取 其他事物修改过的数据,得到不同的值)
按理来说是 (在这次事物中 希望多次读取都可以得到这个值,希望这个值是可重复读的)

简单总结:就是一个事物多次查询一条数据、结果每次读到的值都不一样,这个过程中可能别的事物会修改这条数据的值,而且修改值后事物提交 了,结果导致人家每次查询到的值都不一样,都查到了提交事物修改过的值,值就是所谓的不可重复读,

可重复读(快照读)

你希望 事物A开始执行,第一次查询得到A值,然后你希望执行的事物期间 一直读到的都是A值 不管其他事物如何更新这个值,哪怕他们提交事物,你就希望你一直读的还是这个A值,那么你希望的就是可重复读

幻读

image.pngimage.pngimage.png

  • 事物A 第一次 查询出来10条数据
  • 事物B 此时插入2条新数据并提交
  • 事物A 相同sql语句第二次查询出来12条数据
  • 此时事物A的操作结果为幻读

一个事物内用一样的sql多次查询,结果每次查询都会发现查到之前一些没有看见过的数据,(其间存在其他事物插入新数据,并提交了事物)

总结

  • 不可重复读:就是一条数据的值没法满足一个事物内多次重复读值都一样,别的事物修改了值之后就不可重复读了
  • 脏写:就是两个事物没提交的情况下,都修改同一提一条数据,结果一个事物回滚了,把另外一个事物修改的值也给撤销了,所谓的脏写就是两个事物没提交状态下修改同一个值
  • 脏读:一个事物修改了一条数据的值,结果还没提交呢,另外一个事物就读到了你修改的值,然后你回滚了,人家事物再次读,就读不到了,就是一个事物读到了另一个事物修改之后还没提交的值,就是脏读
  • 幻读:一个事物用一样的sql多次查询,每次都会查询发现之前没有出现过的数据

问题本质

这些问题的本质,都是数据库的多事物并发问题,为了解决多事物并发问题,数据库设计了事物隔离机制、MVCC多版本隔离机制、锁机制,用一种套机制来解决多事物并发问题