• 简述事务隔离级别


    1. 前言(可直接跳过)

    数据库使用中经常遇到的一个概念:事务隔离级别,各种数据库的官方文档也有很详细的解释,但是里面存在大量的数据库专业术语,刚接触的同学可能很难理解。我们先看看几个隔离级别的概念,看完后肯定会晕。

    1.1 事务

    数据库事务指的是一组数据操作,事务内的操作要么就是全部成功,要么就是全部失败,也就是要么commit,要么rollback。就像我们一个网购付款的操作,用户付款后要涉及到订单状态更新、扣库存以及其他一系列动作,这就是一个事务,一切正常那就相安无事,一旦中间有某个环节异常,那整个事务就要回滚,如果是更新了订单状态但是不扣库存,那就很有可能没有货发了。事务具有原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)四个特性,简称ACID,缺一不可。今天要说的就是隔离性。

    1.2 事务隔离级别

    读未提交(READ UNCOMMITTED)最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读、不可重复读。

    读提交 (READ COMMITTED)允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读、不可重复读仍有可能发生。

    可重复读 (REPEATABLE READ)
    对同一行数据多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读、不可重复读,但幻读仍有可能发生。

    串行化(SERIALIZABLE)最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读和幻读。

    1.3 事务数据问题

    脏读

    脏读指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并不一定最终存在的数据,这就是脏读。

    可重复读

    可重复读指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据都是一致的。通常针对数据更新(UPDATE)操作。

    不可重复读

    对比可重复读,不可重复读指的是在同一事务内,不同的时刻读到的同一批数据可能是不一样的,可能会受到其他事务的影响,比如其他事务改了这批数据并提交了。通常针对数据更新(UPDATE)操作。

    幻读

    幻读是针对数据插入(INSERT)操作来说的。假设事务A对某些行的内容作了更改,但是还未提交,此时事务B插入了与事务A更改前的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现好像刚刚的更改对于某些数据未起作用,但其实是事务B刚插入进来的,让用户感觉很魔幻,感觉出现了幻觉,这就叫幻读。

    事务隔离其实就是为了解决上面的脏读、不可重复读、幻读的数据问题,下图是隔离级别对这些问题可能出现的对照表:
    在这里插入图片描述
    上面都是官方文档对事务隔离级别的基本描述,但是这样太难理解了,下面正文。

    2. 正文

    一开始,我们这个数据库隔离级别是RU。打个比方,现在我想买电脑,我比较喜欢拯救者,看了一款非常不错,准备付款,老板从我的银行卡扣了12000 (开启事务,update),就在这个时候,老婆突然查询了我的银行卡余额 (select),发现我的余额少了12000 (脏读),非常生气。这个时候,我发现这台拯救者待机时间太短了,我又想买Mac,厚着脸皮找老板把拯救者退了 (rollback),晚上回到家,门口放着一个键盘…

    第二天,我决定把数据库的事务级别调整到RC,这样只有在我确定走出商铺(commit),老婆才能查询到银行卡的扣款记录,不至于跪键盘。于是我再次踏进商铺,这次我看好了Mac,准备付款(开启事务),一看价格14000,马上查了下银行卡余额还有15000 (select),刚刚够,只是有点肝疼。我说跑个分看看性能怎么样。说时迟那时快,老婆拿用微信(绑定的同一张银行卡)付款买了个2000的包 (update),立马付款(commit),这动作简直就是迅雷不及掩耳盗铃之势。这时,我也下定决心要付款了,结果店员查了下 (select),说我余额不够,只有13000 (不可重复读)。我心中万马奔腾,刚刚卡里明明有钱的?这里出现了不可重复读!导致我一次事务内两次查询的余额不一样。晚上回去求了老婆半天,她才决定向我的银行卡里充了1000元,我决定狠心一次,把事务级别调整到RR。这样在我开始付款(update),直到走出商铺(commit)这个期间,老婆的所有查询都是我付款前的余额,并且不能够再花刷卡付款(update)。这就是可以重复读了,不会出现在一次事务中读取同一条数据不一致的问题,其他人要想看到这次消费,必须在我走出商铺之后(commit),才能看到这次的余额变化,终于,我买到了电脑,不容易啊。最后,我想看下其他银行卡里面是不是还有钱,于是,我开启事务,看了一下,很遗憾,一共就有1张银行卡(count),余额是0。谁知,老婆候决定把日常家庭消费和一次是消费分开管理,于是又给我办了一张银行卡 (insert),而我正在看着余额怀疑人生的时候,有一股神秘力量让我又按下了查询键,结果,哇,居然出来了两张卡(count),我怀疑自己是不是出现了幻觉 (幻读)??这就是RR,无法解决幻读问题,它只能锁定一行数据的修改(update),但是其他人仍然可以随时执行insert操作!你在一个事务内仍然可能会读出两次不一样的结果,要想避免出现这个,只能采取最高的隔离等级,Serializable!读写互相阻塞,这样可以避免以上所有问题,但是,我为什么要这样做呢…
    上面这个小故事只是帮大家更好的理解数据库的隔离级别,不一定十分准确,还是要以官方文档为准,最后,祝愿大家都能买到称心如意的电脑。

  • 相关阅读:
    Spring集成Junit完成JdbcTemplate修改和删除,jdbc内容和配置解耦合
    net.schmizz.sshj.DefaultConfig Illegal key size问题,NIFI部分版本因此无法正常启动
    【MySQL】第6篇--连接池
    【STM32学习(4)】STM32简述定时器
    代码随想录刷题|LeetCode 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组
    MQ---第一篇
    图论-二分图
    TiO2包覆聚苯乙烯纳米杂化微球/超顺磁性Fe3O4/聚苯乙烯复合微球/纳米TiO2复合粒子的相关性能
    车载以太网物理层SerDes
    React 像 vue 一样配置页面路由,并支持重定向路由,路由守卫等(使用 useRoutes 完成)...
  • 原文地址:https://blog.csdn.net/qq_38871652/article/details/132888257