当前位置: 首页 > 科技观察

数据库脏读、不可重复读、幻读示意图

时间:2023-03-18 01:19:48 科技观察

Overview分享数据库脏读、不可重复读、幻读的相关笔记,做个备忘!如果没有事务隔离会怎样?假设我们现在有这样一张表(T),里面记录了很多伟人的名字。让我们看看如果我们不隔离事务会发生什么。第一天,事务A访问数据库,它做了一件事,把新人的名字加入数据库,但是没有提交事务。insertintoTvalues(4,'牛D');这时又来了一个事务B,他想查询所有牛的名字。selectNamefromT;这时候如果事务之间没有有效的隔离,事务B返回的结果中就会出现“牛D”的名字,这就是“脏读”。第二天,事务A访问数据库,想查询ID为1的人才姓名,于是执行selectNamefromTwhereID=1;这时事务B来了,因为ID为1的人才改了名字,所以要更新,提交事务。updateTsetName='不好'whereID=1;然后,事务A又想看到ID为1的好人的名字,于是执行了selectNamefromTwhereID=1;结果读出两次ID为1的好人的名字是不一样的,这就是不可重复读(unrepeatableread)。第三天,事务A访问了数据库,他想看看数据库中的专家是谁,于是执行了select*fromT;这时事务B来了,给数据库增加了一位新的专家。insertintoTvalues(4,'牛D');这时事务A忘记了刚才的好人是谁,所以又执行了一次。从T中选择*;结果第一次是三个伟人,第二次是四个好人。相信此时交易A是一头雾水。刚刚发生了什么?这种情况称为“幻象问题”。为了防止脏读、不可重复读、幻读等,我们需要根据实际需要设置数据库的隔离级别。下面介绍这方面的内容。数据库事务隔离级别数据库事务隔离级别(递减级别)有四种:1.Serializable(序列化):最严格的级别,事务串行执行,资源消耗***;2.REPEATABLEREAD(重复读取):保证一个事务不会修改已经被另一个事务读取但未提交(回滚)的数据。它避免了“脏读”和“不可重复读”的情况,但不能避免“幻读”,反而带来更多的性能损失。3.READCOMMITTED(提交读):大多数主流数据库默认的事务级别保证一个事务不会读取另一个并行事务修改但未提交的数据,避免“脏读”,但无法避免“幻读”和“不可重复读取”。此级别适用于大多数系统。4、ReadUncommitted(读未提交):事务中的修改,即使没有提交,也可以被其他事务看到,这会导致“脏读”、“幻读”和“不可重复读”。脏读、不可重复读和幻读:一个数据库可能有多个访问客户端。当这些客户端并发访问数据库时,如果不采取必要的隔离措施,将会存在以下问题。这些问题分为5类,包括3类数据读取问题:脏读、不可重复读和幻读。两种数据更新问题:第一种丢失更新,第二种丢失更新。1、脏读A事务读取B事务未提交的变化数据,并以此数据为基础进行操作。此时如果事务B回滚,A事务读取的数据是不被识别的。比如常见的取款交易和转账交易:2.不可重复读不可重复读是指事务A读取了事务B已经提交的变化数据,如果A在取款交易的过程中,B转100给账户,A两次读取的余额不一致。3.幻读A事务读取了B事务提交的新数据,会造成幻读问题。幻读一般发生在计算统计数据的事务中。例如,银行系统在同一笔交易中两次统计存款账户的总额。两次统计中,刚刚新增了一个存款账户,存入了100。两次统计的总量是不一致的。注意:不可重复读和幻读的区别是:前者是指读取已提交事务的变化数据(修改或删除),后者是指读取其他已提交事务的新数据。不同的方法用于解决这两个问题。防止读取和更改数据,只需要对操作的数据加行级锁,就可以防止操作中的数据发生更改。其次,为了防止新数据被读取,往往需要加表级锁,对整个表进行加锁,防止新增数据(oracle使用多版本数据实现)。4、通俗解释:脏读:所谓脏读,其实就是读取其他事务回滚前的脏数据。例如,事务B在执行过程中,修改了数据X。在提交之前,事务A读取X,但事务B回滚。这样,事务A就变成了脏读。也就是说,当前事务读取的数据是其他事务想要修改但没有修改成功的数据。不可重复读:事务A先读取一段数据,然后执行逻辑时,事务B更改了数据,然后事务A再次读取时,发现数据不匹配,就是so-称为不可重复读。也就是说,当前事务先读取一次数据,然后再次读取的数据是其他事务修改成功的数据,导致两次读取的数据不匹配,这也对应了不可重复读的语义。幻读:事务A先根据条件索引获取N条数据,然后事务B更改这N条数据以外的M条数据或者添加满足事务A查找条件的M条数据,导致事务A再次查找,发现有N+条数据时,出现幻读。也就是说,当前事务第一次取到的数据小于后面读取到的数据项。不可重复读和幻读对比:两者有些相似,但前者是针对update或delete,后者是针对insert。为什么会出现“脏读”?因为没有规则就没有“选择”操作。为什么会出现“不可重复读”?因为“更新”操作是没有规则的。为什么会出现“幻读”?因为“插入”和“删除”操作是没有规则的。“ReadUncommitted”可以防止什么?没有什么。“ReadCommitted”可以防止什么?使用“快照读”可以避免“脏读”,但可能会出现“不可重复读”和“幻读”。“重复红”能预防什么?使用“SnapshotRead”锁定读取记录,避免“脏读”和“不可重复读”,但可能会出现“幻读”。“Serializable”可以防止什么?坐成一排,吃蔬菜水果,可以有效避免“脏读”、“不可重复读”和“幻读”,但效果谁用过就知道了。