数据库的隔离级别www.bifa9999com

一.事务的概述

   上一章节里,重点讲到了锁,以及锁与事务的关系。离上篇发布时间好几天了,每天利用一点空闲时间还真是要坚持。听《明朝那些事儿》中讲到”人与人最小的差距是聪明,人与人最大的差距是坚持”很经典的一句话一直记得。这篇重点围绕事务来开展。涉及的知识点包括:事务的概述,事务并发控制模型,并发产生的负面影响,事务隔离级别以及不同的表现。本章多以文字描述为主,没有多少代码量,重点是阐述不同隔离级别的不同表现,在以后的业务中,涉及到事务时,本文可以用来做个参考。

1.1 事务ACID

   
事务作为一个逻辑工作单元执行一系列的操作,它包括四个属性:原子性、一致性、隔离性和持久性
(ACID) 属性, 只有这样才能成为一个事务。  

   
原子性:当一个事务被当作一个单独的工作单元时,不管事务内有什么,都是一个整体。对于其数据修改,要么全都执行,要么全都不执行。  

     
 一致性:事务在完成时,必须使所有的数据都保持一个逻辑一致状态。   

  隔离性:并发事务所做的修改必须与其他并发事务所做的修改隔离。
事务能识别数据所处的状态,要么是另一并发事务修改它之前的状态,要么是并发事务修改它之后的状态。

  持久性:一但事务完全,它的效果是永久存于系统的。该修改即使出现系统故障也将一直保持。
SQL Server 2014和更高版本启用延迟的持久事务。

1.2 事务的操作模式有几下几种:

  自动提交事务:每条单独的语句都是一个事务。

  显式事务:每个事务均以 BEGIN TRANSACTION 语句显式开始,以 COMMIT 或
ROLLBACK 语句显式结束。

  隐式事务:在前一个事务完成时新事务隐式启动,但每个事务仍以 COMMIT 或
ROLLBACK 语句显式完成。

  批处理级事务:只能应用于多个活动结果集 (MARS),在 MARS
会话中启动的 Transact-SQL 显式或隐式事务变为批处理级事务。在sql
server 2000 必须对每个 SqlCommand 对象使用独立的 SqlConnection
对象。但是 SQL Server 2005 启用了 MARS,可以共用一个SqlConnection
对象。

       本章重点讲到显式事务的隔离级别

关于数据库事务隔离级别的介绍

二. 事务并发模型

www.bifa9999com,  2.1 并发访问是指:多用户同时访问一种资源被视为并发访问资源。
并发数据访问需要某些机制,以防止多个用户试图修改其他用户正在使用的资源时产生负面影响,机制就是下面讲的事务隔离级别。处于活动状态而不互相干涉的并发用户数据越多,并发性就越好。当一个正在修改数据的用户阻止了其他用户读取数据,或者当一个正在读取数据的用户阻止了其它用户修改数据时,并发性就降低了。

  2.2 并发类型

    在sqlserver里数据库系统可以采用两种方式来管理并发数据访问:乐观并发控制和悲观并发控制,在sql
server 2000以前只有悲观并发。乐观并发控制是一种称为行版本控制(row
versioning)的技术支持。这二种技术并发控制的区别在于:是在冲突发生前进行防止,还是在发生后采用某种方法来处理冲突。

  悲观并发控制

      在悲观并发中,sql
server是获取锁来阻塞对于其它用户正在使用数据的访问。
 用户操作的读与写之间是会互相阻塞的。

       乐观并发控制

    乐观并发控制默认采用行版本控制使其它用户能够看到修改操作发生以前的数据状态,旧版本数据行会保存下来。因些读取数据不会受到其它用户正对该数据进行修改操作的影响,换言之修改数据不会受到其它用户正对该数据进行读取影响。
因为读取用户访问的数据行是一个被保存过的版本。
 用户读与写之间不会互相阻塞,但写与写还是会发生阻塞。

  2.3  事务并发带来的负面影响

       修改数据的用户会影响同时读取或修改相同数据的其他用户。
即这些用户可以并发访问数据。
如果数据存储系统没有并发控制,则用户可能会看到以下负面影响:

并发影响 

定义

丢失更新                                                            

       当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。 每个事务都不知道其他事务的存在。   最后的更新 将覆盖由其他事务所做的更新,这将导致数据丢失。 

脏读

 当一个用户修改了数据但尚未提交修改,而另一个正在读取的用户会读到这个修改从而导致不一致的状态发生。

不可重复读

一个用户在同一个事务中分别以两个读操作间隔读取相同资源时可能会得到不同的值。

虚拟读取(幻影)

一个事务里执行两个相同的查询,但第二个查询返回的行集合是不同的,此时就会发生虚拟读取。这种情况发生在where 查询中,比如 where count(1)<10。  同一个事务中多次使用相同的条件查询,select操作返回不同数据的结果集。

事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。例如,银行转账工作:从一个账号扣款并使另一个账号增款,这两个操作要么都执行,要么都不执行。所以,应该把它们看成一个事务。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。

三.事务隔离级别

  在sql server 2005及以上
支持五种隔离级别来控制“读”操作的行为,其中有三个是悲观并发模式,一个是乐观并发模式,剩下一个存在两种模式。 下面介绍隔离级别从允许的并发负作用(例如脏读或虚拟读取)的角度进行描述。

隔离级别

 定义

未提交读
READUNCOMMITTED 

 隔离事务的最低级别,未提交读不会发出共享锁,允许脏读,一个事务可能看见其他事务所做的尚未提交的更改。未提交读不会发出共享锁. 该项的作用与与SELECT表上加NOLOCK相同。

 

已提交读
READ COMMITTED

 一个事务不能读取其它事务修改但未提交的数据,避免了脏读。事务内语句运行完后便会释放共享锁,而不是等到事务提交的时候。 这是数据库引擎默认级别。

可重复读
REPEATABLE READ

 事务内查询语句运行完后不会释放共享锁,而是等到事务提交后.其它事务不能修改,删除,但可以插入新数据。
 因为不是范围锁,可能发生虚拟读取

 可序列化SERIALIZABLE

 隔离事务的最高级别,事务之间完全隔离。 阻止其它事务删除或插入任何行。 相当于SELECT上加HOLDLOCK相同, SELECT 操作使用 WHERE 子句时获取范围锁,主要为了避免虚拟读取

已提交读 快照隔离
READ COMMITTED SNAPSHOT ISOLATION level (RCSI)

当 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON 时,已提交读隔离使用行版本控制提供语句级读取一致性。 读取操作只需要 SCH-S 表级别的锁,不需要页锁或行锁。 使用行版本控制为每个语句提供一个在事务上一致的数据快照,因为该数据在语句开始时就存在。 

快照隔离
SNAPSHOT ISOLATION level
(SI)

 快照隔离级别使用行版本控制来提供事务级别的读取一致性。 读取操作不获取页锁或行锁,只获取 SCH-S 表锁。 读取其他事务修改的行时,读取操作将检索启动事务时存在的行的版本。 当 ALLOW_SNAPSHOT_ISOLATION 数据库选项设置为 ON 时,只能对数据库使用快照隔离。 默认情况下,用户数据库的此选项设置为 OFF。

  sql
server主要是通过共享锁申请和释放机制的不同处理,来实现不同的事务隔离级别。不同隔离级别允许的并发副作用如下:

隔离级别 脏读 不可重复读 幻影读 并发控制模型
 未提交读 悲观
 已提交读 悲观
 已提交读快照 乐观
 可重复读 悲观
 快照 乐观
可串行化 悲观

  不同隔离级别对共享锁的不同处理方式如下:

隔离级别 是否申请共享锁 何时释放 有无范围锁
未提交读  
已提交读 当前语句做完时
可重复读 事务提交时
可序列化 事务提交时

针对上面的描述可以看出,事务的提出主要是为了解决并发情况下保持数据一致性的问题。

四.事务隔离不同表现

* *  设置未提交读 

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

 设置提交读 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

    设置可重复读

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 

   4.1 未提交读和提交读与其它事务并发,的区别如下表格:

未提交读

提交读

其它事务

SELECT Model FROM Product

WHERE SID=10905

显示model 值为test

SELECT Model FROM Product 

WHERE SID=10905

显示model 值为test

begin  tran

update  product set model=’test1′

where SID=10905

SET TRANSACTION ISOLATION
LEVEL READ UNCOMMITTED

SET TRANSACTION ISOLATION 

LEVEL READ COMMITTED

 这个事务将model值改为test1.

 此时修改的X锁未释放

 

SELECT Model FROM Product

WHERE SID=10905

显示model值为test1,但这并不正确,

因为其它事务还没有提交。没有获取共享锁

 

SELECT Model FROM Product

WHERE SID=10905

查询被阻塞

申请获取共享锁时失败,因为X锁未释放

 

  阻塞消失,得到的值还是test

 rollback tran

这里事务回滚了x锁释放,值还是test

   4.2  已提交读和可重复读与其它事务并发,的区别如下表格:

已提交读

可重复读 其它事务

SET TRANSACTION ISOLATION
LEVEL READ UNCOMMITTED
begin tran
SELECT Model FROM
ProductWHERE SID=10905
第一次查询显示model值为 test

SET TRANSACTION ISOLATION
LEVEL REPEATABLE READ
begin tran
SELECT Model FROM Product
WHERE SID=10905
第一次查询显示model值为 test

 

   

begin tran
update product set model=’test1′
where SID=10905
将model值改为 test1

另一事务是已提交读时,这里事务修改成功
提交读共享锁查询后就释放。

另一事务是可重复读时,这里事务修改阻塞
可重复读共享锁一直保留到事务提交

SELECT Model FROM Product
WHERE SID=10905
第二次查询值显示为 test1

SELECT Model FROM Product
WHERE SID=10905
第二次查询显示值显示为 test

 

commit tran

这里就是一个事务里多次读取同一值
结果可能不一致

  commit tran  

   未完…sql server 锁与事务拨云见日(下)

事务具有以下4个基本特征。


Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败。


Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态。


Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。

● Durability(持久性):事务结束后,事务处理的结果必须能够得到固化。

数据库肯定是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况。

● 更新丢失(Lost
update):两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来。

● 脏读取(Dirty
Reads):一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险的,因为很可能所有的操作都被回滚。

● 不可重复读取(Non-repeatable
Reads):一个事务对同一行数据重复读取两次,但是却得到了不同的结果。例如,在两次读取的中途,有另外一个事务对该行数据进行了修改,并提交。

● 两次更新问题(Second lost updates
problem):无法重复读取的特例。有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一次写操作失效。

● 虚读(Phantom
Reads):事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有另外一个事务插入数据造成的。

数据库的隔离级别

为了避免上面出现的几种情况,在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同。

● 未授权读取(Read
Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。

● 授权读取(Read
Committed):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。

● 可重复读取(Repeatable
Read):禁止不可重复读取和脏读取,但是有时可能出现幻影数据。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。


序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read
Committed,它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、虚读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

通过前面的介绍已经知道,通过选用不同的隔离等级就可以在不同程度上避免前面所提及的在事务处理中所面临的各种问题。所以,数据库隔离级别的选取就显得尤为重要,在选取数据库的隔离级别时,应该注意以下几个处理的原则:

首先,必须排除“未授权读取”,因为在多个事务之间使用它将会是非常危险的。事务的回滚操作或失败将会影响到其他并发事务。第一个事务的回滚将会完全将其他事务的操作清除,甚至使数据库处在一个不一致的状态。很可能一个已回滚为结束的事务对数据的修改最后却修改提交了,因为“未授权读取”允许其他事务读取数据,最后整个错误状态在其他事务之间传播开来。

其次,绝大部分应用都无须使用“序列化”隔离(一般来说,读取幻影数据并不是一个问题),此隔离级别也难以测量。目前使用序列化隔离的应用中,一般都使用悲观锁,这样强行使所有事务都序列化执行。

剩下的也就是在“授权读取”和“可重复读取”之间选择了。我们先考虑可重复读取。如果所有的数据访问都是在统一的原子数据库事务中,此隔离级别将消除一个事务在另外一个并发事务过程中覆盖数据的可能性(第二个事务更新丢失问题)。这是一个非常重要的问题,但是使用可重复读取并不是解决问题的唯一途径。

假设使用了“版本数据”,Hibernate会自动使用版本数据。Hibernate的一级Session缓存和版本数据已经为你提供了“可重复读取隔离”绝大部分的特性。特别是,版本数据可以防止二次更新丢失的问题,一级Session缓存可以保证持久载入数据的状态与其他事务对数据的修改隔离开来,因此如果使用对所有的数据库事务采用授权读取隔离和版本数据是行得通的。

“可重复读取”为数据库查询提供了更好的效率(仅对那些长时间的数据库事务),但是由于幻影读取依然存在,因此没必要使用它(对于Web应用来说,一般也很少在一个数据库事务中对同一个表查询两次)。

也可以同时考虑选择使用Hibernate的二级缓存,它可以如同底层的数据库事务一样提供相同的事务隔离,但是它可能弱化隔离。假如在二级缓存大量使用缓存并发策略,它并不提供重复读取语义(例如,后面章节中将要讨论的读写,特别是非严格读写),很容易可以选择默认的隔离级别:因为无论如何都无法实现“可重复读取”,因此就更没有必要拖慢数据库了。另一方面,可能对关键类不采用二级缓存,或者采用一个完全的事务缓存,提供“可重复读取隔离”。那么在业务中需要使用到“可重复读取”吗?如果你喜欢,当然可以那样做,但更多的时候并没有必要花费这个代价。

一、数据库事务
1、事务是作为单个逻辑工作单元执行的一系列操作。可以是一条SQL语句也可以是多条SQL语句。
2、事务具有四个特性
原子性:不可分隔、成则具成、败则具败。
隔离性:独立的执行互不干扰。由并发事务所作的修改必须与任何其他并发事务所作的修改隔离(另外的描述:多个事务同时进行,它们之间应该互不干扰.应该防止一个事务处理其他事务也要修改的数据时,不合理的存取和不完整的读取数据)
3、启动事务:使用 API 函数和 Transact-SQL
语句,可以按显式、自动提交或隐式的方式来启动事务。
4、结束事务:您可以使用 COMMIT(成功) 或 ROLLBACK(失败)
语句,或者通过 API 函数来结束事务。
5、创建事务的原则:
尽可能使事务保持简短很重要,当事务启动后,数据库管理系统 (DBMS)
必须在事务结束之前保留很多资源、以保证事务的正确安全执行。
特别是在大量并发的系统中, 保持事务简短以减少并发
资源锁定争夺,将先得更为重要。
1、事务处理,禁止与用户交互,在事务开始前完成用户输入。
2、在浏览数据时,尽量不要打开事务
3、尽可能使事务保持简短。
4、考虑为只读查询使用快照隔离,以减少阻塞。
5、灵活地使用更低的事务隔离级别。
6、灵活地使用更低的游标并发选项,例如开放式并发选项。
7、在事务中尽量使访问的数据量最小。

二、事务的隔离级别

1、数据库事务的隔离级别:四种

           

  

隔离级别

  

  

脏读(Dirty    Read)

  

  

不可重复读(NonRepeatable    Read)

  

  

幻读(Phantom    Read)

  

读未提交(Read uncommitted)

可能

可能

可能

读已提交(Read committed)

不可能

可能

可能

可重复读(Repeatable read)

不可能

不可能

可能

可串行化(Serializable )

不可能

不可能

不可能

2、数据库一般的默认隔离离级别是“读已提交”,默认的事务隔离级别下:Insert,update
,delete下的是X锁, 会等待事务完成。通常情况下可以把隔离级别设为Read
Commited,它能避免脏读,而且有较好的并发性能。尽管它会导致不可重复读、虚读和第二类更新丢失等问题,在可能出现这类问题的个别场合可以由应用程序釆用悲观锁或乐观锁来控制。

3、SQL语句可以使用SET TRANSACTION ISOLATION
LEVEL来设置事务的隔离级别。如:SET TRANSACTION ISOLATION LEVEL Read
Committed。若要在应用程序中使用更严格或较宽松的隔离级别,可以通过使用
set transaction isolation
level语句设置会话的隔离级别,来自定义整个会话的锁定。
指定隔离级别后,sql
server会话中所有select语句的锁定行为都运行于该隔离级别上,并一直保持有效直到会话终止或者将隔离级别设置为另一个级别。

4、另外要提一点:SQL标准对事务隔离级别的规定,是按该级别不可能发生什么问题来确定的,不一定会发生这样的问题;所以,不同的数据库对事务隔离的级别约定不一样,比如,有的数据库把
可重复读级别按可串行化来对待。(lkdlhw_2000个人理解:各个数据库应该都遵循四种标准的事务隔离等级的定义,但是某些数据库具体实现可能不存在四种,因为串行化可以避免不可重复读,因此某些数据库语法上支持设置事务隔离等级为不可重复读,但实际上是串行化在起作用。也就是说只要该级别能够避免不可重复读的问题,就可以称之为不可重复读取级别。)

5、该隔离级别定义一个事务必须与其他事务所进行的资源或数据更改相隔离的程度。事务隔离级别控制:
读取数据时是否占用锁以及所请求的锁类型。
占用读取锁的时间。
引用其他事务修改的行的读取操作是否:
在该行上的排他锁被释放之前阻塞其他事务。
检索在启动语句或事务时存在的行的已提交版本。
读取未提交的数据修改

三、锁

1、分类:从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁

2、事务使用锁,防止其他用户修改另外一个还没有完成的事务中的数据。对于多用户系统来说,锁机制是必须的。SQL
Server有多种锁,允许事务锁定不同的资源。锁就是保护指定的资源,不被其他事务操作。SQL
Server有多种锁,允许事务锁定不同的资源。锁就是保护指定的资源,不被其他事务操作。为了最小化锁的成本,SQL
Server自动地以与任务相应等级的锁来锁定资源对象。锁定比较小的对象,例如锁定行,虽然可以提高并发性,但是却有较高的开支,因为如果锁定许多行,那么需要占有更多的锁。锁定比较大的对象,例如锁定表,会大大降低并发性,因为锁定整个表就限制了其他事务访问该表的其他部分,但是成本开支比较低,因为只需维护比较少的锁。

3、 锁的特点:

  1. 锁是保证并发控制的手段
  2. 可以锁定的资源包括行、页、簇、表和数据库
  3. 锁的类型主要包括共享锁和排它锁
  4. 特殊类型的锁包括意图锁、修改锁和模式锁
  5. 共享锁允许其他事务继续使用锁定的资源
  6. 排它锁只允许一个事务访问数据
  7. 系统本身可以处理死锁
  8. 用户可以根据实际情况定制锁的一些特征

4、锁是定义到sql语句上的,对数据进行操作的sql就是:select,Insert,update
,delete。不同的事物隔离即被在执行sql的时候会向表上发送不同的锁。

四、多个用户同时对数据库的并发操作时会带来以下数据不一致的问题:

脏读dirty reads:
当事务读取还未被提交的数据时,就会发生这种事件。举例来说:Transaction1修改了一行数据,然后Transaction2在Transaction1还未提交修改操作之前读取了被修改的行。如果Transaction1回滚了修改操作,那么Transaction2读取的数据就可以看作是从未存在过的。
不可重复的读non-repeatable reads:
当事务两次读取同一行数据,但每次得到的数据都不一样时,就会发生这种事件。举例来说:Transaction1读取一行数据,然后Transaction2修改或删除该行并提交修改操作。当Transaction1试图重新读取该行时,它就会得到不同的数据值(如果该行被更新)或发现该行不再存在(如果该行被删除)。
虚读phantom read:
如果符合搜索条件的一行数据在后面的读取操作中出现,但该行数据却不属于最初的数据,就会发生这种事件。举例来说Transactio1读取满足某种搜索条件的一些行,然后Transaction2插入了符合Transaction1的搜索条件的一个新行。如果Transaction1重新执行产生原来那些行的查询,就会得到不同的行。

为了解决这些问题,数据库引入了“锁”的机制(从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁,详细内容不再描述)。

五、lkdlhw_2000个人理解(以下问题都是推测,还没有证实):

隔离级别是由锁来实现的,之所以出现事务的隔离级别相当于数据库开发商根据一般的业务需求实现定义好的一组锁使用的规则,便于我们时候,当我们将事务隔离级别定义到某一级上后如果不能满足需求,我们还可以自行定义sql的锁来覆盖事务隔离级别默认的锁机制?

锁存在两个问题:一个是锁的粒度,一个是锁的时间,锁的时间应该包括两种一种是sql执行完就释放锁,领一中是事务结束后释放锁

六、事务隔离级别的例子

  1. Read
    Uncommitted:最低等级的事务隔离,仅仅保证了读取过程中不会读取到非法数据。上诉4种不确定情况均有可能发生。
  2. Read
    Committed:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
    第一个查询事务
    SET TRANSACTION ISOLATION LEVEL Read Committed
    begin tran
    update Cate SET Sname=Sname+’b’ where ID=1
    SELECT * FROM cate where ID=1
    waitfor delay ’00:00:6′
    rollback tran –回滚事务
    select Getdate()
    SELECT * FROM cate where ID=1
    第二个查询事务
    SET TRANSACTION ISOLATION LEVEL Read committed –把committed换成Read
    uncommitted可看到“脏读取”的示例。
    SELECT * FROM cate where ID=1
    select Getdate()
    可以看到使用 Read Committed 成功的避免了“脏读取”.
  3. Repeatable
    Read:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
    第一个查询事务
    SET TRANSACTION ISOLATION LEVEL Repeatable Read — 把Repeatable
    Read换成Read committed可以看到“不可重复读取”的示例
    begin tran
    SELECT * FROM cate where ID=33 –第一次读取数据
    waitfor delay ’00:00:6′
    SELECT * FROM cate where ID=33 –第二次读取数据,不可重复读取
    commit
    第二个查询事务
    SET TRANSACTION ISOLATION LEVEL Read committed
    update cate set Sname=Sname+’JD’ where ID=33
    SELECT * FROM cate where ID>30
    4.
    Serializable:最高等级的事务隔离,上面3种不确定情况都将被规避。这个级别将模拟事务的串行执行。
    在第一个查询窗口执行
    SET TRANSACTION ISOLATION LEVEL Serializable —
    把Serializable换成Repeatable Read 可看到“幻像读”的示例
    begin tran
    SELECT * FROM cate where ID>30 –第一次读取数据,“幻像读”的示例
    waitfor delay ’00:00:6′ –延迟6秒读取
    SELECT * FROM cate where ID>30 –第一次读取数据
    commit
    第二个查询事务
    SET TRANSACTION ISOLATION LEVEL Read committed
    Delete from cate where ID>33
    SELECT * FROM cate where ID>30
    创建事务

设置事务级别:SET TRANSACTION ISOLATION LEVEL
开始事务:begin tran
提交事务:COMMIT
回滚事务:ROLLBACK
创建事务保存点:SAVE TRANSACTION savepoint_name
回滚到事务点:ROLLBACK TRANSACTION savepoint_name