丢失数据(Lost Update)
在下表中,T1、T2、T3、T4表示时间顺序
-----------------------------------------------------------
用户    T1           T2           T3            T4
A                   X=40         X=X-30B       X=40                                   X=X-20
-----------------------------------------------------------
假设用户A和B都读取X(X=40),然后分别把X减少30和20.用户A在T3把改后的X(X=10)写入数据库.随后,用户B在T4把改后的X(X=20)写入数据库.于是对用户A而言,他的修改在T4处丢失了.脏读数据(Dirty Read)
请看下表,
-----------------------------------------------------------
用户     T1           T2         T3             T4
A       X=40         X=X+30                     ROLLBACKB                               X=70
-----------------------------------------------------------
用户A在T2把X增加了30(尚未写入数据库),用户B在T3由数据缓存读出X=70.但用户A在T4
时撤消(Undo)了对X的修改,数据中仍维持X=40.但用户B已把数据(X=70)取走.不能重复读(Non-Repeatable Read)
--------------------------------------------------------------------------------------------
用户     T1           T2         T3                T4              T5             T6
A                    X=40       Y=30 X+Y=70                                       Z=30 X+Y+Z = 100
B       X=40                                     X=X+20           COMMIT          X=X-20
用户A、用户B分别读取X=40后,在T3用户取出Y=30并计算X+Y=70。在T4时用户B把 X增加20,并于T5把(X=60)
写入数据库。在T6时间,用户A取出Z(Z=30)并继续计算X+Y+Z=100。但如果用户A为进行核算而把X、Y、Z重读
一次再进行计算,却出现X+Y+Z = 120! (X已增加20)。

解决方案 »

  1.   

    这些估计你没有实际试验,是猜的吧!
    其实Non-Repeatable Read是有行锁的。
    解决办法很简单:
    1.采用存储过程更新。
      create procedure change_x @a integer
      as 
      begin
        update yourtab set x = x - a
      end
      即可保证
    2.如果一定要将x读到客户端
      update yourtable set x=x-a where x=70
      假如你读的客户端x是70
      这样,你判断是否有更新@@RowCount>0,表示没人修改过x,修改成功
      如果没有修改@@RowCount=0表示你读的数据已经脏了。
    3.其实很多开发工具直接支持这样操作
      如:Delphi,如果用Post更新,你可以设定TDataBase中的隔离级别,或
      TQuery中的UpdateMode
      

  2.   

    如过没有记忆错误,以上的情况是在SQL2000的参考资料中出现的。关键问题是设定适当的锁定。以上问题,基本上通过行锁定就可以防止问题的出现。特别是有进行数据修改的进程都应该进行锁定。如果是关键的计算,也应该对数据进行锁定。具体如何锁定是比较复杂的。
    有关问题请参见:
    http://www.microsoft.com/china/msdn/technic/develop/database/12
      

  3.   

    to:dobetterthatnthink() http://www.microsoft.com/china/msdn/technic/develop/database/12打不开