菜鸟日记01------MySQL之脏读、不可重复读、幻读

脏读

  是指当前事务读取到其他事务未提交的数据

  例子:有事务a,b和一条记录 id为1,name为张三的数据。

      1、b首先进行更新操作,将name的值由张三改为李四,但是未提交事务

       

      2、然后a进行查询操作,查询姓名为李四 

           

      然后b由于某种原因被回滚,name自然从李四恢复到了张三
  然后a就懵逼了,我TM读取的是李四,但是你现在在数据库中却TM给我存储的是张三,我TM到底要用哪个?

  这就是脏读-----事务a读取到事务b未提交的数据

不可重复读

  是指同一事务中前后查询不一致的问题

  例子:

    a先查询了一条记录,name为张三

     1 select name from stu where id = 1 

    然后b执行了更新,并且还提交

    

    a再次按相同条件进行查询,name为李四

    1 select name from stu where id = 1

    a就会出现懵逼,同样的查询语句,两次得到的执行结果却不一样。

    其实在并发条件下,假如两条select语句间有另外一个事务对name执行了update操作还提交了,把张三的这个值改成了李四,a再次执行同样查询导致name由张三变为李四

    a这时候就有意见了,我TM明明没有对name进行修改,可是为什么会变成李四?谁TM改我数据了。

    这就是不可重复读:同一事务中前后查询不一致

    会导致程序运行变得不可预期、不可控

幻读

  是指一次事务中前后数据量发生变化,用户产生不可预料的问题

   分类:1、并发删除 2、并发插入

   1、并发插入

   a先查询一条记录,name为张三

   1 select name from stu where id = 1

  b插入了一条数据,name为李四

   1 insert into stu(name)values('李四')

  当a再次按相同条件查询

   1 select name from stu where id = 1

  结果多了一条李四的记录,然后a懵逼了,将才明明只有一条一条记录,怎么突然多出来了 一条,感觉出现了幻觉

  2、并发删除

  a先查询一条记录,name为张三

   1 select name from stu where id = 1

  b删除了这条数据

   1 delete from stu where id =1

  然后a在再次执行相同条件查询的时候,就会懵逼,怎么张三的记录消失了呢,将才还在呢,怎么TM又没了,再此出现幻觉

  这就是幻读----一次事务中前后数据量发生变化,用户产生了不可预料的问题

  总结:

    1、事务a读取某一个范围的数据,第二次读取同样范围的数据,记录数发生变化(增多或减少)即为幻读

    2、select 读取的数据的方式是快照读,update读取的数据方式是当前读,即其他事务更新/新增/删除的数据都会被读取到并进行了更新

不同点:

  1、不可重复读 的重点是修改,幻读 的重点在于插入或者删除

  2、虽然不可重复读和幻读都是读取另外一个提交的事务,但是,不可重复读查询的是同一个数据项,幻读针对的是一批数据整体(个数)

  3、从控制的角度出发

    不可重复读只需锁住满足条件的记录即可

    幻读不光需要锁住满足条件的记录还需锁住其相近的记录

 

解决方法:

  要解决以上问题,需要用到 事务的隔离级别 

  1、脏读  ----> 禁止写时读,避免了‘脏读’,对应隔离级别 read committed(读已提交)

 

  2、不可重复读  ----->紧张读时写,避免了‘不可重复读’,对应隔离级别 repeatable read(可重复读)

  3、幻读  ---->要把整个表给锁住,需要使用到serialize

  当然,隔离级别越高,并行度越低,付出的代价就越大

posted @   临渊行舟  阅读(151)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
点击右上角即可分享
微信分享提示