不可重复读与幻读个人理解

我对数据库这块了解不深,这两者意思是蛮相近的感觉有必要了解透彻些,为此也查了好几篇其他人的文章。
首先谈谈事务(transaction)
以下都是个人理解,如有错误望海涵与指明

事务有4个特性

  1. A(Atomic) 原子性:事务是一系列指令动作的集合,这一系列指令要么全完成,要么全都不完成。也就是说如果执行到某一指令时出现异常,会回滚到最初的状态。这些指令是不可分割的,像原子一样。
  2. C(Consistence)一致性:其实事务的隔离性保证了事务的一致性。在一个事务中,数据库中的数据是不会突然因为另一个事务的某些指令而变化的。也就保证了数据的一致性。
  3. I(Isolation)隔离性:事务之间应当是互不影响的,当两个事务并发执行时,一个事务的改变不应当对另一个事务产生影响。
  4. D(Durability)持久性:事务完成后所产生的结果在数据库中是有持久性的。也就是说一个事务结束了,对数据库CRUD了,数据库变了就是变了,不会再过阵子回滚成原来的样子。

本文的重点是RR与PR

RR(Repeatable read)

RR是数据库隔离级别中的第3级。 数据库中隔离级别一共有4级

先简单说下4个隔离级别:

  1. Read Uncommitted:
    最低端的隔离级别,脏读,不可重复读,幻读,全部都能出现。
    两个事务并发时,事务2还未提交时对数据库的CRUD(R会不会不太确定)也会对事务1产生影响。而未提交代表有回滚的可能性,一旦回滚了,事务1读到的就是脏数据。打个比方两个人给同一个账号存钱,B刚存了1块钱,A看到账号里余额1觉得够多了不用存了,可B用的ATM其实有问题,没存上,过会给B退出来了一个钢镚。那么A就读到了脏数据,账号现在还是0元而A还以为有1块钱。所以说这种隔离级别说白了感觉都算不上隔离了。
  2. Read committed:
    大多数数据库的隔离级别,能防止脏读,防不住重复读与幻读
    这种隔离级别保证了两个事务并发时,事务2只有提交后,才会对事务1产生影响。这就防止了脏读。但它防不住重复读,也就是这篇文章的重点之一。那么到底什么是不可重复读呢?通俗来讲事务1读到了一个数据,这时并发的事务2修改了这个数据,并且提交了。那么事务1再读这个数据的时候,数据就变了。也就是不可重复读。 描述起来易于理解,但是让我困惑的就是接下来和幻读的对比了。
  3. Repeatable Read
    Mysql数据库的隔离级别,除了幻读都能防住
    这就是RR,它是个隔离级别,能防住重复读时数据的变化,但防不住PR(幻读)。那到底什么是PR呢?很多篇文章的大意是事务A读了一次数据之后事务B插入了一个数据,事务A再读时还是之前所读到的东西(可重复读)但是实际上里面的数据已经多了一条。这时如果再创建多的这一条数据(因为事务A不知道这数据已经存在了)或者修改与之相关的数据,就会产生错误了。

听起来幻读好像有点像脏读啊,但其实不是,脏读是读的就是错的数据。而幻读读的不是错的,只是少读了点什么。 那为什么会是事务B是插入数据导致的幻读呢?删除不行么?为什么RR防的住重复读防不住幻读呢?其实根本还是在理解这4种隔离级别的实现方式。是靠上锁实现的。

共享锁

多个事务并发时,首个占用共享锁的事务拥有对数据读写的权力,其他事务仅拥有的权力。

排他锁

多个事务并发时,首个占用排他锁的事务拥有对数据读写的权力,其他事务都是弟弟。

1.Read uncommitted隔离级别实现:

事务在写数据的时候会占用共享锁,写完就释放锁。也就是说仅能保证多个事务并发时一个事务在写数据的同时,其他事务都可以读,不能写。(其他事务当然不能写了,那不乱套了么。)这个隔离级别也就这点保证了。

2.Read committed隔离级别实现:

说完第一个,第二个就好想了。事务在写数据的时候会占用排他锁,事务结束再释放锁,你这么想,事务A要读一个数据,事务B写了这个数据,如果事务B用的是共享锁的话,之后事务A读到的就是事务B写的数据,然后事务B回滚了,事务A就产生了脏读。所以要用互斥锁,等到事务B结束后再释放锁。

3.Repeatable Read隔离级别实现:

第二种隔离级别实现不可重复读是正常的。事务A在事务B占用排他锁前先读了这个数据,事务B写了这个数据,事务B结束后,事务A再读,这个数据自然就变了。
应对这个的办法就是在事务要读数据的时候,加个共享锁,这样就妥了,事务A占用了共享锁,读了数据,事务B想占用排他锁写,不行,因为共享锁不给你写的权力。等事务A处理完读到的数据,释放共享锁后,事务B才开始占用排他锁,写这个数据。这就保证了可重复读。

但为什么没有防止幻读呢?
要知道共享锁锁住的可只有当前读到的数据,这也就解释了为什么只能增加一条数据,因为删除或修改数据都被共享锁保护了啊。当然也就解释了RR防不住幻读的原因。

发布了26 篇原创文章 · 获赞 6 · 访问量 6466

猜你喜欢

转载自blog.csdn.net/weixin_43975128/article/details/96424276