`
如若_晴
  • 浏览: 111680 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

数据库弱一致性四个隔离级别

 
阅读更多

原文转自;http://www.cnblogs.com/xwdreamer/archive/2011/01/18/2297042.html

 

SQL-92标准中定义了四个隔离级别,这四个隔离级别在以前版本的SQL Server中即受到支持:

READ UNCOMMITTED

READ UNCOMMITTED是限制性最弱的隔离级别,因为该级别忽略其他事务放置的锁。使用READ UNCOMMITTED级别执行的事务,可以读取尚未由其他事务提交的修改后的数据值,这些行为称为“脏”读。这是因为在Read Uncommitted级别下,读取数据不需要加S锁,这样就不会跟被修改的数据上的X锁冲突。比如,事务1修改一行,事务2在事务1提交之前读取了这一行。如果事务1回滚,事务2就读取了一行没有提交的数据,这样的数据我们认为是不存在的。

READ COMMITTED

READ COMMITTED(Nonrepeatable reads)SQL Server默认的隔离级别。该级别通过指定语句不能读取其他事务已修改但是尚未提交的数据值,禁止执行脏读。在当前事务中的各个语句执行之间,其他事务仍可以修改、插入或删除数据,从而产生无法重复的读操作,或“影子”数据。比如,事务1读取了一行,事务2修改或者删除这一行并且提交。如果事务1想再一次读取这一行,它将获得修改后的数据或者发现这一样已经被删除,因此事务的第二次读取结果与第一次读取结果不同,因此也叫不可重复读。

实验1

query1:事务1

复制代码
--step1:创建实验数据
select * into Employee from AdventureWorks.HumanResources.Employee
alter table Employee add constraint pk_Employee_EmployeeID primary key(EmployeeID)

--step2:设置隔离级别,这是数据库的默认隔离界别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED

--step3:开启第一个事务
BEGIN TRAN tran1
    --step4:执行select操作,查看VacationHours,对查找的记录加S锁,在语句执行完以后自动释放S锁
    SELECT EmployeeID, VacationHours
        FROM Employee 
        WHERE EmployeeID = 4;

    --step5:查看当前加锁情况,没有发现在Employee表上面有锁,这是因为当前的隔离界别是READ COMMITTED
    --在执行完step2以后马上释放了S锁.
    SELECT request_session_id, resource_type, resource_associated_entity_id,
        request_status, request_mode, resource_description
        FROM sys.dm_tran_locks
复制代码

查看锁的情况如下图所示,我们发现在只有在数据库级别的S锁,而没有在表级别或者更低级别的锁,这是因为在Read Committed级别下,S锁在语句执行完以后就被释放

query2:事务2

复制代码
--step6:开启第二个事务
BEGIN TRAN tran2;
    --step7:修改VacationHours,需要获得排它锁X,在VacationHours上没有有S锁
    UPDATE Employee 
        SET VacationHours = VacationHours - 8  
        WHERE EmployeeID = 4;

    --step8:查看当前加锁情况
    SELECT request_session_id, resource_type, resource_associated_entity_id,
        request_status, request_mode, resource_description
        FROM sys.dm_tran_locks
复制代码

在开启另外一个update事务以后,我们再去查看当前的锁状况,如下图所示,我们发现在表(Object)级别上加了IX锁,在这张表所在的Page上也加了IX锁,因为表加了聚集索引,所以在叶子结点上加了X锁,这个锁的类型是KEY

然后我们回到事务1当中再次执行查询语句,我们会发现查询被阻塞,我们新建一个查询query3来查看这个时候的锁状况,其查询结果如下,我们可以发现查询操作需要在KEY级别上申请S锁,在Page和表(Object)上面申请IS锁,但是因为Key上面原先有了X锁,与当前读操作申请的S锁冲突,所以这一步处于WAIT状态。

如果此时提交事务2的update操作,那么事务1的select操作不再被阻塞,得到查询结果,但是我们发现此时得到的查询结果与第一次得到的查询结果不同,这也是为什么将read committed称为不可重复读,因为同一个事物内的两次相同的查询操作的结果可能不同

REPEATABLE READ

REPEATABLE READ是比READ COMMITTED限制性更强的隔离级别。该级别包括READ COMMITTED,并且另外指定了在当前事务提交之前,其他任何事务均不可以修改或删除当前事务已读取的数据。并发性低于 READ COMMITTED,因为已读数据的共享锁在整个事务期间持有,而不是在每个语句结束时释放。比如,事务1读取了一行,事务2想修改或者删除这一行并且提交,但是因为事务1尚未提交,数据行中有事务1的锁,事务2无法进行更新操作,因此事务2阻塞。如果这时候事务1想再一次读取这一行,它读取结果与第一次读取结果相同,因此叫可重复读。

实验2

query1:事务1

复制代码
--step1:创建实验数据
select * into Employee from AdventureWorks.HumanResources.Employee
alter table Employee add constraint pk_Employee_EmployeeID primary key(EmployeeID)

--step2:设置隔离级别
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

--step3:开启第一个事务
BEGIN TRAN tran1
    --step4:执行select操作,查看VacationHours
    SELECT EmployeeID, VacationHours
        FROM Employee 
        WHERE EmployeeID = 4;

    --step5:查看当前加锁情况,发现在Employee表上面有S锁,这是因为当前的隔离界别是REPEATABLE READ
    --S锁只有在事务执行完以后才会被释放.
    SELECT request_session_id, resource_type, resource_associated_entity_id,
        request_status, request_mode, resource_description
        FROM sys.dm_tran_locks
复制代码

查询锁状态的结果如下图所示,我们发现在KEY上面加了S锁,在Page和Object上面加了IS锁,这是因为在Repeatable Read级别下S锁要在事务执行完以后才会被释放

 query2:事务2

复制代码
--step6:开启第二个事务
BEGIN TRAN tran2;
    --step7:修改VacationHours,需要获得排他锁X,在VacationHours上有S锁,出现冲突,所以update操作被阻塞
    UPDATE Employee 
        SET VacationHours = VacationHours - 8  
        WHERE EmployeeID = 4;
复制代码

执行上述update操作的时候发现该操作被阻塞,这是因为update操作要加排它锁X,而因为原先的查询操作的S锁没有释放,所以两者冲突。我们新建一个查询3执行查询锁状态操作,发现结果如下图所示,我们可以发现是WAIT发生在对KEY加X锁的操作上面。

此时再次执行查询1中的select操作,我们发现查询结果跟第一次相同,所以这个叫做可重复读操作。但是可重复读操作并不是特定指两次读取的数据一模一样,Repeatable Read存在的一个问题是幻读,就是第二次读取的数据返回的条目数比第一次返回的条目数更多。

比如在Repeatable Read隔离级别下,事务1第一次执行查询select id from users where id>1 and id <10,返回的结果是2,4,6,8。这个时候事务1没有提交,那么对2,4,6,8上面依然保持有S锁。此时事务2执行一次插入操作insert into user(id) valuse(3),插入成功。此时再次执行事务1中的查询,那么返回结果就是2,3,4,6,8。这里的3就是因为幻读而出现的。因此可以得出结论:REPEATABLE READ隔离级别保证了在相同的查询条件下,同一个事务中的两个查询,第二次读取的内容肯定包换第一次读到的内容。

SERIALIZABLE 

SERIALIZABLE 是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。该级别包括REPEATABLE READ,并增加了在事务完成之前,其他事务不能向事务已读取的范围插入新行的限制。比如,事务1读取了一系列满足搜索条件的行。事务2在执行SQL statement产生一行或者多行满足事务1搜索条件的行时会冲突,则事务2回滚。这时事务1再次读取了一系列满足相同搜索条件的行,第二次读取的结果和第一次读取的结果相同。

重复读与幻读

重复读是为了保证在一个事务中,相同查询条件下读取的数据值不发生改变,但是不能保证下次同样条件查询,结果记录数不会增加。

幻读就是为了解决这个问题而存在的,他将这个查询范围都加锁了,所以就不能再往这个范围内插入数据,这就是SERIALIZABLE 隔离级别做的事情。

隔离级别与锁的关系

  1. 在Read Uncommitted级别下,读操作不加S锁;
  2. 在Read Committed级别下,读操作需要加S锁,但是在语句执行完以后释放S锁;
  3. 在Repeatable Read级别下,读操作需要加S锁,但是在事务提交之前并不释放S锁,也就是必须等待事务执行完毕以后才释放S锁。
  4. 在Serialize级别下,会在Repeatable Read级别的基础上,添加一个范围锁。保证一个事务内的两次查询结果完全一样,而不会出现第一次查询结果是第二次查询结果的子集。

 

分享到:
评论

相关推荐

    数据库事务的四大特征以及隔离级别

    一致性(Consistency):一个事务执行之前和执行之后都必须处于一致性状态。 隔离性(Isolation):并发的事务是相互隔离的,即一个事务内部的操作及正在操作的数据必须封锁起来,不能被其他企图修改的事务看到。 ...

    DB2中的四个隔离级别

    DB2 中的四个隔离级别 DB2 支持四种隔离级别,分别是可重复读(Repeatable Read)、读稳定性(Read Stability)、游标稳定性(Cursor Stability)和未落实的读(Uncommitted Read)。每种隔离级别都有其特点和应用...

    MySQL数据库:事务隔离级别.pptx

    隔离性强制对事务进行某种程度的隔离,保证应用程序在事务中看到一致的数据。 MySQL提供了下面4种隔离级:序列化(SERIALIZABLE)、可重复读(REPEATABLE READ)、提交读(READ COMMITTED)、未提交读(READ ...

    数据库的隔离级别介绍

    总的来说,数据库隔离级别的选择是一个权衡过程,需要在数据一致性、并发性和性能之间找到合适的平衡点。在设计数据库系统和应用程序时,理解这些隔离级别及其可能产生的效果至关重要,以便做出最佳决策。

    spring常用数据库事务传播属性和事务隔离级别1

    在实际应用中,开发者需要根据业务需求来选择合适的事务传播属性和隔离级别,以达到最佳的事务管理和数据一致性。例如,对于需要独立运行的操作,可以选择 REQUIRES_NEW;而对于需要保证数据一致性的查询,可能需要...

    数据库四个级别 详解

    总结来说,数据库的四个隔离级别是为了解决并发执行时的数据不一致问题,它们分别是未提交读、提交读、可重复读和序列化可读,分别对应不同的数据一致性与并发性能的权衡。理解并合理选择这些隔离级别对于构建可靠且...

    数据库进阶,隔离级别.pdf

    数据库事务隔离级别是指在并发环境中,数据库系统对事务的处理规则,以保证事务的原子性、一致性、隔离性和持久性。事务的隔离级别决定了事务之间的相互影响程度。 1. Atomicity(原子性) 事务的原子性是指事务...

    MySQL的四种事务隔离级别

    事务具有四个基本要素,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),这四个要素是事务正确执行的保障。 1. 原子性是指事务包含的所有操作要么全部完成,要么全部不...

    数据库事务的隔离级别1

    数据库事务的隔离级别是数据库管理系统在并发环境中保证数据一致性、避免脏读、不可重复读和幻读等问题的关键机制。在数据库领域,ACID(原子性、一致性、隔离性、持久性)理论是事务处理的基本原则。 1. **原子性...

    Hibernate 事物隔离级别 深入探究

    为了确保数据库的可靠性和一致性,Hibernate 提供了四种事务隔离级别,分别是 Serializable、Repeatable Read、Read Committed 和 Read Uncommitted。 一、Serializable 隔离级别 Serializable 隔离级别是最高级别...

    ORACLE的隔离级别

    高隔离级别可以保证数据的一致性,但可能影响数据库的性能;低隔离级别可以提高数据库的性能,但可能出现数据不一致的情况。 通过合理地设置隔离级别,可以提高数据库的性能和安全性,满足不同的应用需求。 隔离...

    数据库事务与隔离级别.docx

    一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账...

    02.Spring支持的常用数据库事务传播属性和事务隔离级别.zip

    在Spring框架中,数据库事务管理是其核心特性之一,它为开发者提供了强大的事务控制能力,使得在多线程、分布式环境下的数据一致性得以保障。本资料主要探讨的是Spring支持的数据库事务传播属性和事务隔离级别。 一...

    数据库事务隔离级别.docx

    不同的隔离级别提供了不同程度的数据一致性保障,同时也会影响系统的并发性能。 #### 三、四种常见的事务隔离级别 根据SQL标准,数据库系统通常支持以下四种事务隔离级别: 1. **Read Uncommitted (读未提交)** -...

    数据库事务与隔离技术

    事务通常包含四个基本属性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),合称为ACID特性。 在SQL SERVER和ORACLE中,事务隔离级别是不同的,它们决定了并发操作时...

    MySQL事务隔离级别

    MySQL事务隔离级别是数据库管理系统中一个非常重要的概念,它关系到数据的一致性和并发性能。在MySQL中,事务被用于确保数据库操作的原子性、一致性、隔离性和持久性(ACID特性)。事务隔离级别主要涉及四个方面:读...

    数据库隔离级别扫描.pdf

    数据库隔离级别是数据库管理系统中用于控制事务之间交互作用的一个关键特性,它旨在解决并发操作中可能出现的数据不一致性和并发问题。在数据库系统中,主要有四种隔离级别,分别是Read Uncommitted、Read Committed...

    事务四大隔离级别的不同

    这四个隔离级别是:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。下面我们将详细探讨这些隔离级别及其在MySQL中的实现和使用方法。 1. **读...

Global site tag (gtag.js) - Google Analytics