脏读、幻读和不可重复读 + 事务隔离级别

1. 脏读 :脏读就是指当一个事务正在访问数据,而且对数据进行了修改,而这种修改尚未提交到数据库中,这时,另一个事务也访问这个数据,而后使用了这个数据
 e.g.
       1.Mary的原工资为1000, 财务人员将Mary的工资改成了8000(但未提交事务)
        2.Mary读取本身的工资 ,发现本身的工资变为了8000,欢天喜地!
       3.而财务发现操做有误,回滚了事务,Mary的工资又变为了1000
         像这样,Mary记取的工资数8000是一个脏数据。
数据库

 

2. 不可重复读 :是指在一个事务内,屡次读同一数据。在这个事务尚未结束时,另一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,因为第二个事务的修改,那么第一个事务两次读到的的数据多是不同的。这样在一个事务内两次读到的数据是不同的,所以称为是不可重复读
   e.g.
   1.在事务1中,Mary 读取了本身的工资为1000,操做并无完成
   2.在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务.
   3.在事务1中,Mary 再次读取本身的工资时,工资变为了2000
并发

 解决办法:若是只有在修改事务彻底提交以后才能够读取数据,则能够避免该问题。高并发

 

3. 幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的所有数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,之后就会发生操做第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉同样
  e.g. 
  目前工资为1000的员工有10人。
  1.事务1,读取全部工资为1000的员工。
  2.这时事务2向employee表插入了一条员工记录,工资也为1000
  3.事务1再次读取全部工资为1000的员工 共读取到了11条记录, 
 
 解决办法:若是在操做事务完成数据处理以前,任何其余事务都不能够添加新数据,则可避免该问题
性能

 

不可重复读的重点是修改 :
 一样的条件, 你读取过的数据,再次读取出来发现值不同了
幻读的重点在于新增或者删除
 一样的条件, 第 1 次和第 2 次读出来的记录数不同
spa

 

参考:http://cupoy.iteye.com/blog/251796.net

http://blog.csdn.net/d8111/archive/2008/06/29/2595635.aspxserver

 http://www.iteye.com/topic/332577blog

 

 

 二、在一个程序中,依据事务的隔离级别将会有三种状况发生。
  
  ◆脏读:一个事务会读进尚未被另外一个事务提交的数据,因此你会看到一些最后被另外一个事务回滚掉的数据。

  ◆不可重复读:一个事务读进一条记录,另外一个事务更改了这条记录并提交完毕,这时候第一个事务再次读这条记录时,它已经改变了

  ◆ 幻影读:一个事务用Where子句来检索一个表的数据,另外一个事务插入一条新的记录,而且符合Where条件,这样,第一个事务用同一个where条件来检索数据后,就会多出一条记录
事务

 

三、数据库提供了四种事务隔离级别, 不一样的隔离级别采用不一样的锁类开来实现. 
在四种隔离级别中, Serializable的级别最高, Read Uncommited级别最低. 
大多数数据库的默认隔离级别为: Read Commited,如Sql Server , Oracle. 
少数数据库默认的隔离级别为Repeatable Read, 如MySQL InnoDB存储引擎
资源

  

SQL SERVER锁的机制 
  SQL server的全部活动都会产生锁。锁定的单元越小,就越能越能提升并发处理能力,可是管理锁的开销越大。如何找到平衡点,使并发性和性能均可接受是SQL Server的难点。
SQL Server有以下几种琐:
  SQL server的全部活动都会产生锁。锁定的单元越小,就越能越能提升并发处理能力,可是管理锁的开销越大。如何找到平衡点,使并发性和性能均可接受是SQL Server的难点。
SQL Server有以下几种琐:

一、 共享锁
用于只读操做(SELECT),锁定共享的资源。共享锁不会阻止其余用户读,可是阻止其余的用户写和修改。

二、 更新锁
更新锁是一种意图锁,当一个事务已经请求共享琐后并试图请求一个独占锁的时候发生更新琐。例如当两个事务在几行数据行上都使用了共享锁,并同时试图获取独占锁以执行更新操做时,就发生了死锁:都在等待对方释放共享锁而实现独占锁。更新锁的目的是只让一个事务得到更新锁,防止这种状况的发生。

三、 独占锁
一次只能有一个独占锁用在一个资源上,而且阻止其余全部的锁包括共享缩。写是独占锁,能够有效的防止’脏读’。

四、 意图缩
在使用共享锁和独占锁以前,使用意图锁。从表的层次上查看意图锁,以判断事务可否得到共享锁和独占锁,提升了系统的性能,不需从页或者行上检查。

五、 计划锁
Sch-M,Sch-S。对数据库结构改变时用Sch-M,对查询进行编译时用Sch-S。这两种锁不会阻塞任何事务锁,包括独占锁。
读是共享锁,写是排他锁,先读后更新的操做是更新锁,更新锁成功而且改变了数据时更新锁升级到排他锁

 

l    DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 . 
l    READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 ) 
l    READ_COMMITTED 会出现不可重复读、幻读问题(锁定正在读取的行) 
l    REPEATABLE_READ 会出幻读(锁定所读取的全部行) 
l    SERIALIZABLE 保证全部的状况不会发生(锁表



 

ReadCommitted: 
假设A事务对正在读取数据Data放置了共享锁,那么Data不能被其它事务改写,因此当B事务对Data进行读取时总和A读取的Data数据是一致的,因此避免了脏读。因为在A没有提交以前能够对Data进行改写,那么B读取到的某个值可能会在其读取后被A更改从而致使了该值不能被重复取得;或者当B再次用相同的where字句时获得了和前一次不同数据的结果集,也就是幻像数据。

ReadUncommitted:
假设A事务即不发布共享锁,也不接受独占锁,那么并发的B或者其它事务能够改写A事务读取的数据,那么并发的C事务读取到的数据的状态和A的或者B的数据均可能不一致,那么。脏读、不可重复读、幻象数据均可能存在。

RepeatableRead:
(注意MSDN原文中的第一句话:在查询中使用的全部数据上放置锁,因此不存在脏读的状况)。
假设A事务对读取的全部数据Data放置了锁,以阻止其它事务对Data的更改,在A没有提交以前,新的并发事务读取到的数据若是存在于Data中,那么该数据的状态和A事务中的数据是一致的,从而避免了不可重复的读取。但在A事务没有结束以前,B事务能够插入新记录到Data所在的表中,那么其它事务再次用相同的where字句查询时,获得的结果数可能上一次的不一致,也就是幻像数据。

Serializable:  在数据表上放置了排他锁,以防止在事务完成以前由其余用户更新行或向数据集中插入行,这是最严格的锁。它防止了脏读、不可重复读取和幻象数据。

相关文章
相关标签/搜索