深入理解数据库事务--脏读、不可重复读,幻读

一.先了解ACID

 原子性(A):一个事务执行过程中,所有步骤要么全部成功,或者全部回滚失败,不能执行其中一部分;

 一致性(C):从一种状态,执行该事务后,转变为另外一种正确状态 ,经典例子:A向B转账,俩者总和不变;

 隔离性( I):为了有效保证并发读取数据的正确性,提出的事务隔离级别;          

 持久性(D):事务执行成功之后,数据不能更改。

二.事务隔离级别 

 在数据库操作中,为了有效保证,并发读取数据的正确性,提出事务隔离级别。数据库锁,也是为了构建这些隔离级别存在的。

隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
未提交读(Read uncommitted)可能可能可能
已提交读(Read committed)不可能可能可能
可重复读(Repeatable read)不可不可可能
可串行化(Serializable )不可能不可能不可能

 1、Read Uncommitted(未提交读):一个事务已对数据修改,但没有提交之前,其他并行事务也可以读到,会导致“脏读”、“幻读”和“不可重复读取”。

 2、READ COMMITTED (提交读):保证一个事务,不会读到其他并行事务,已修改,但未提交的数的数据。换句话说:只能读取到已经提交的数据。提交读,可能会出现“幻读”和“不可重复读取”。(Oracle、SqlServer采用默认隔离级别)

 3、REPEATABLE READ(重复读):保证一个事务,不会修改已经由另一个事务读取但未提交(回滚)的数据。换句话说:

在同一个事务内的查询都是事务开始时刻一致的。重复读,可能会出致“幻读”。(Mysql采用默认隔离级别)

 4、Serializable (串行化):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞;

三.脏读、不可重复读、幻读

(1)概念

   脏读:所谓的脏读,其实就是读到了别的事务回滚前的脏数据。比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。

   不可重复读:事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。

   幻读:事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条数据,或增加了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。

  也就是说,事务A第一次读取到的数据,比后一次读取到数据条量少。

(2)不可重复读和幻读区别

    两者有些相似,但是前者针对的是update或delete,后者针对的insert。

(3)重复读和幻读原理分析

  在可重复读中,该sql第一次读取到数据后,就将这些数据加锁(悲观锁),其它事务无法修改这些数据,就可以实现可重复读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。

   但是MySQL、ORACLE、PostgreSQL等成熟的数据库,出于性能考虑,都是使用了以乐观锁为理论基础的MVCC(多版本并发控制)来实现。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值