对于脏读,不可重复读,幻读的一点理解,看懂红字很关键

事务4个隔离界别

Read Uncommitted, Read commited, Repeatable read, Serializable
Read Uncommitted.  最低的隔离级别,Read Uncommitted最直接的效果就是一个事务可以读取另一个事务并未提交的更新结果。

Read Committed.  Read Committed通常是大部分数据库采用的默认隔离级别,它在Read Uncommitted隔离级别基础上所做的限定更进一步, 在该隔离级别下,一个事务的更新操作结果只有在该事务提交之后,另一个事务才可能读取到同一笔数据更新后的结果。 所以,Read Committed可以避免Read Uncommitted隔离级别下存在的脏读问题, 但,无法避免不可重复读取和幻读的问题。

Repeatable Read.  Repeatable Read隔离级别可以保证在整个事务的过程中对同一笔数据的读取结果是相同的,不管其他事务是否同时在对同一笔数据进行更新,也不管其他事务对同一笔数据的更新提交与否。 Repeatable Read隔离级别避免了脏读和不可重复读取的问题,但无法避免幻读。(mysql默认隔离级别

Serializable.  最为严格的隔离级别,所有的事务操作都必须依次顺序执行,可以避免其他隔离级别遇到的所有问题,是最为安全的隔离级别, 但同时也是性能最差的隔离级别,因为所有的事务在该隔离级别下都需要依次顺序执行,所以,并发度下降,吞吐量上不去,性能自然就下来了。 因为该隔离级别极大的影响系统性能,所以,很少场景会使用它。通常情况下,我们会使用其他隔离级别加上相应的并发锁的机制来控制对数据的访问,这样既保证了系统性能不会损失太大,也能够一定程度上保证数据的一致性。

并发问题

脏读

 (针对未提交数据)如果一个事务中对数据进行了更新,但事务还没有提交,另一个事务可以“看到”该事务没有提交的更新结果,这样造成的问题就是,如果第一个事务回滚,那么,第二个事务在此之前所“看到”的数据就是一笔脏数据。

不可重复读

针对其他提交前后,读取数据本身的对比)不可重复读取是指同一个事务在整个事务过程中对同一笔数据进行读取,每次读取结果都不同。如果事务1在事务2的更新操作之前读取一次数据,在事务2的更新操作之后再读取同一笔数据一次,两次结果是不同的,所以,Read Uncommitted也无法避免不可重复读取的问题。

幻读

针对其他提交前后,读取数据条数的对比) 幻读是指同样一笔查询在整个事务过程中多次执行后,查询所得的结果集是不一样的。幻读针对的是多笔记录。在Read Uncommitted隔离级别下, 不管事务2的插入操作是否提交,事务1在插入操作之前和之后执行相同的查询,取得的结果集是不同的,所以,Read Uncommitted同样无法避免幻读的问题。

不可重复读和幻读区别

对于不可重复读和幻读,可以借用下面的例子理解:

不可重复读

不可重复读的重点是修改:

同样的条件, 你读取过的数据, 再次读取出来发现值不一样了

例子:

在事务1中,Mary 读取了自己的工资为1000,操作并没有完成 

Java代码  收藏代码
  1. con1 = getConnection();  
  2. select salary from employee empId ="Mary";  
在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务. 
Java代码  收藏代码
  1. con2 = getConnection();  
  2. update employee set salary = 2000;  
  3. con2.commit();  
在事务1中,Mary 再次读取自己的工资时,工资变为了2000 
Java代码  收藏代码
  1. //con1  
  2. select salary from employee empId ="Mary";  
在一个事务中前后两次读取的结果并不致,导致了不可重复读。
幻读
幻读的重点在于新增或者删除 (数据条数变化)

同样的条件, 第1次和第2次读出来的记录数不一样

例子:

目前工资为1000的员工有10人。 
事务1,读取所有工资为1000的员工。 

Java代码  收藏代码
  1. con1 = getConnection();  
  2. Select * from employee where salary =1000;  
共读取10条记录 

这时另一个事务向employee表插入了一条员工记录,工资也为1000 
Java代码  收藏代码
  1. con2 = getConnection();  
  2. Insert into employee(empId,salary) values("Lili",1000);  
  3. con2.commit();  
事务1再次读取所有工资为1000的员工 
Java代码   收藏代码
  1. //con1  
  2. select * from employee where salary =1000;  
共读取到了11条记录,这就产生了幻读。 




  • 33
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值