Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1799123
  • 博文数量: 600
  • 博客积分: 10581
  • 博客等级: 上将
  • 技术积分: 6205
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-06 10:13
文章分类
文章存档

2016年(2)

2015年(9)

2014年(8)

2013年(5)

2012年(8)

2011年(36)

2010年(34)

2009年(451)

2008年(47)

分类:

2009-10-11 11:36:57

来源:CWW

上回提到了OpenResultset方法,可以有以下数种型态的Cursor
rdOpenForwardOnly  rdOpenStatic	rdOpenDynamic	rdOpenKeyset	
也提及了SQL Server/ Informix的Server/Client端Cursor与之搭配的记录,再来讨论
OpenResultset的 LockType,这LockType的设定主要是为了多人同时使用的环境而设。

rdConcurReadOnly 1      (预设值)唯读的。
rdConcurLock     2      悲观的平行。
rdConcurRowVer   3      基於资料列 ID之乐观的平行。
rdConcurValues   4      基於资料列值之乐观的平行。
rdConcurBatch    5      使用批次模式更新之乐观的平行处理。为每一笔成功地被
                        更新的资料列传回 Status 值。

而我们这里针对的是前4者加以讨论。
如果是rdUseODBC 的Client端Cursor,上回提过,它只能有rdOpenForwardOnly 及
rdOpenStatic两种型态(使用其他型态时,可能也不会有误,但行为只有这两种模式)
而使用的锁定模式呢,只能是rdConcurReadOnly/rdConcurValues 而其他的锁定模式呢
使用下去,可能会有错,也可能没有,那要看ODBC Driver的厂商如何写,但其锁定行模
式应只有上述说的这两种(rdConcurBatch我未研究)。

如果是Server端的Cursor(rdUseServer),那才能使用这前四种锁定方式;rdConcurReadOnly
不用多说,那代表该Cursor不是Update Cursor,只能读取。而rdConCurLock是悲观的锁
定,根据我的Testing ,SQL Server6.5 其悲观的锁定的特性是:只要在OpenResultset
时,者就会在RowSetSize数目的列上做一个Update Lock,如果是Page Lock的状态,那
至少会把各个Row所在的Page上的列全Lock住,因此Lock住的列可不只RowSetSize的数目
。当然,这只是某些情况之下会如此,SQL SERVER会看实际的情况来Handle Lock,说不
定会Lock整个Table也不一定。这里要提一下Lock的种类:

Share Lock : 同时之间有很多Procee可以Share Lock住某一笔资料,一般读取时有时会
             在上面做个Share Lock(并不是每一种都会,要看我们先前的设定)
Exclusive Lock : 某一笔Record不能有其他的任何Lock(含Share Lock)时,才能Lock成,
             一般在update/delete等动作时,会先Exclusive Lock该笔,成功时才能再
             做往後的动作。
Update Lock:或称Promotable Lock,这个Lock是为了Current Record有所更动而设计,
            它允许Share Lock与之共存,但不可以有其他的Exclusive/Update Lock存
            在。它在真的要Update时会把Update Lock提升成Exclusive Lock,所以啦,
            在它真的要Update前於其上的所有Lock(包括Share Lock)都要解除才能成功。
+----------------+---------------------------------------------------- 
|                |           目前已有的Lock                          |
|----------------+---------+-----------+------------+----------------|
|想要完成之Lock  | no lock | Share Lock| Update Lock| Exclusive Lock |
|----------------|---------+-----------+------------+----------------|
|share lock      |   可         可          可            不可       |  
|update lock     |   可         可         不可           不可       |
|exclusive lock  |   可        不可        不可           不可       |
|----------------+---------------------------------------------------+

以下我暂且用Row Lock来解释一些东西,读者可另外推及Page Lock。

一、SQL Server6.5的 rdConCurLock(悲观的锁定)

    这个rdConCurLock会在它读过的Row上做一个Update Lock,那代表什麽?代表其他
的Process如果想读取rdConcurLock方式读过的资料,那没有问题,因为读取的动作顶多
是Share Lock甚而是没有Lock,方才提过,同一Record允许多个Share Lock於其上,所
以只是读取资料时没有问题。如果说Process A 以rdConcurLock方式的Cursor目前指向
ResultSet的第5笔资料,另外有一个Process B 使用乐观锁定的Cursor,且ResultSet成
员相同,而它正指向第1笔资料,Process B 想要来更新资料时会如何?答案是可能无法
更新,因为rdConcurLock已读过第1笔资料,所以在上面做了一个Update Lock,Process B
想Update它,前题是要先能Exclusive Lock该笔,但因其上已有Update Lock所以Lock不成
,而Lock 不成的情况下会如何,那要看我们设定Lock时TimeOut的时间是多少,一次Lock
不成会自动再试着Lock,如果在TimeOut的时间内Lock成功便OK(那更新便可成功),否则就
会产生一个Error。而rdConCurLock的Update Lock何时才会Releas呢?可能是Close ResultSet
或Transaction结束等等。正因rdConCurLock会在其上放Update Lock,所以它不允许其他的
Process也在相同的Resultset上以rdConCurLock的方式开启。相反的,方才的例子中,如果
Process A回头想Update 第一笔资料时则会成功,因为乐观的锁定在读取到资料後,便会
Release Share Lock而变成没有Lock,这在乐观锁定中再详谈。

二、OpenLink的Informix ODBC Driver没有提供rdConcurLock的功能
    就算我们以rdConcurLock的方式来OpenResultset,也不会有错,只是其行为是乐观
的锁定,除非,设定Isolation Level才会有Lock在上面,这容後再述。    

三、SQL的乐观锁定
   乐观锁定分成两种:rdConcurValues/ rdConcurRowVer,这二者的区别主要在於:确定
想修改的那个Row,在读取与想修改之间有没有被其他Process修改过的认知。如果是
rdConcurValues那代表使用的是各个栏位的值,而rdConcurRowVer则是利用Timestamp,
TimeStamp是SQL Server自动维护的一个栏位,当某个Row有更新时,便会自动更新於其上
的TimeStamp栏位,所以我们Update时,SQL Server会用原始读出的TimeStamp值与目前的
TimeStamp值做一比较,如果不同代表先前已被别人Update了,因此rdConcurRowver比较有
效率。而Table中就要有timestamp的栏位才能使用rdConcurRowver,否则在OpenResult时
会产生一个Warnning。除此之外,这两种乐观锁定似乎没有太大不同。

    乐观锁定很奇特,它在读取出资料时(如OpenResultSet)会产生Share Lock,而读取出
资料之後的所有Record含Current Record竟然没有做锁定(连Share Lock也没有),而且不管
我们的Cursor是否是Update Cursor都如此,只有在Update时才会去做Exclusive Lock。如
果,这个Update指令是under Transaction那这Exclusive Lock不会去除,等Transaction
Committed/RollBack 时才Release。再来一个Case,如果Process A以乐观锁定的方式来
开启Resultset,Process B也以乐观的锁定开启相同的Resultset,而且二者同时皆指向同
一笔Record,Process A先行Update该笔,而後Process B再想Update时,会产生错误,如果
是以rdOpenKetset/rdOpenDynamic方式那Process B便得先rs.Move 0, rs.Edit重新修正
资料最後再rs.Update一次。请和先前一个Process是悲观锁定,一个是乐观锁定而Update
不同笔资料做一比较,为何之前的Update指令会等待Process A的Resultset 去除锁定,
而这个例子是什麽也不等,一下子就产生Error?(提示:这个例子中,Process A update
之後便Release Lock变成没有Lock),当然这个例子是没有Under Transaction时的记录,
反过来,如果Under Transaction呢,Process A先Update该Reocrd後未Commit/Rollback
前,在该笔(或其所在的Page)会有一个Exclusive Lock,此时如果Process B来Update时
则会进入等待,直到Procees A如果Commit Transaction则Process B的Update产生Error
或者Process A Rollback Transaction则Process B的Update可成功。

    这和我原本的想像不同,我原本的想法,Server端的Cursor是由Declare Cursor/
Open Cursor/Fetch/Close Cursor等指令直接来做,但是我查一些书,得知如果是Update 
Cursor在Fetch到资料时,会在Current Record所在的Page上做Update Lock,如果不是Update
Cursor则做Share Lock,而且其Lock会一直保存,直到下一个Fetch或Close Cursor或
Commit/Rollback Transaction等,而不是像现在只有读出的那一个时点会做Lock,读出後
便不Lock了。这中间的行为模式之不同,应是ODBC与Server端的Cursor间另有一个机制所造成
,而我不知这中间的机制是什麽。
             
四、InforMix的乐观锁定
    基本上,Informix的乐观锁定和SQL Server没有太大的不同,然而Informix提供Row
Lock的功能,这是和SQL Server不同之处。

上面说明了ODBC乐观锁定和悲观锁定的行为模式,基本上,说明的是读取到资料之後,与
Updtae资料之後,使用何种Lock於Current Record或读取过的Record,而我上面的说明全
来自我的Testing,我分别使用SQL EnterPrise Manager与Informix Sysmaster Database
的syslocks Table来查寻Lock的情况。但这里还有一个重点没有说到,那就是什麽情况之
下才能顺利"读取到"资料;而上面的讨论是读取成功之後,有没有要在Object上做Lock。
这是Set Transaction Isolation Level的讨论范围。请查下一个Topic
阅读(764) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~