在实际的多用户并发访问的生产环境里边,我们经常要尽可能的保持数据的一致性。
乐观锁定解决方案 8n#;6
@{!C~V e<%
-- 首先我们在Card表里边加上一列F_TimeStamp 列,该列是varbinary(8)类型.但是在更新的时候这个值会自动增长. ]Ri^90 Z
V% "fXl7
alter table Card add F_TimeStamp timestamp not null )r5 qZP
aM J}^`
,EPJ>"<
-- 悲观锁定 U. X1qM
declare @CardNo varchar(20) Pt!,PI
declare @timestamp varbinary(8) h"kU&{
declare @rowcount int "g"&f^e!
!u_6pu{
Begin Tran *3UAI>zNK
<@Ch {Zfk
-- 取得卡号和原始的时间戳值 ~uc$"]
select top 1 @CardNo=F_CardNo, M ,8 2uI
@timestamp=F_TimeStamp &jpLK{d(,
from Card s]}?oJ kp
where F_Flag=0 [@#[~6=G
$i0}oCO@
-- 延迟50秒,模拟并发访问. eq4f6Hge
waitfor delay '000:00:50' k7+6FkEO*
n3<p#q,Gf
-- 注册卡,但是要比较时间戳是否发生了变化.如果没有发生变化.更新成功.如果发生变化,更新失败. x_y:
,`>0nqi<Y
update Card t~%9
set F_Name=user, 4UvMjL^0C
F_Time=getdate(), tJSTIMgC
F_Flag=1 V%<Uc}?4!
where F_CardNo=@CardNo and F_TimeStamp=@timestamp n5HF{oa?
set @rowcount=@@rowcount [oX1_iT#
if @rowcount=1 }7lI.L(Z
begin $U`q)RR
print '更新成功!' KP( E
commit TgD0]wuv/
end %;8WR`GlXR
else if @rowcount=0 T\F4\0%
begin `.wF1Wf
if exists(select 1 from Card where F_CardNo=@CardNo) b1u5YCx
begin !x)6d!2V
print '此卡已经被另外一个用户注册!' Zf,MS(lS
rollback tran V#Tm^kN.
end OJZ0 ArW
else a".>{
begin 7Y9u8Xqo
print '并不存在此卡!' R{VP9ynn
rollback tran #(O=Rj_yo
end SrqGTYl798
end q(|D1RX
G;DtA
在另外一个窗口里边执行没有waitfor的代码,注册成功后,返回原来的窗口,我们就会发现到时间后它显示的提示是此卡以被另外一个用户注册的提示.很明显,这样我们也可以避免两个用户同时注册一张卡的现象的出现.同时,使用这种方法的另外一个好处是没有使用更新锁,这样增加的系统的并发处理能力. s[8$-b
hjaJX=5
上边我详细介绍了乐观锁定和悲观锁定的使用方法,在实际生产环境里边,如果并发量不大,我们完全可以使用悲观锁定的方法,因为这种方法使用起来非常方便和简单.但是如果系统的并发非常大的话,悲观锁定会带来非常大的性能问题,所以我们就要选择乐观锁定的方法. G[ ^Jl;
lm6bd?YA
如果大家发现文章里边有什么错误的地方,请及时提醒我,也欢迎有兴趣的一起研究讨论.