有二个事务T、U,下面的并发操作是否正确,若不正确请使用时间戳方法解决其冲突。   ts(T)<ts(U)      T                                U    read(b)                                  read(b)                                 write b=b+300   write b=b-300 设有二个事务T、U,下面的并发操作是否正确,若不正确请使用时间戳方法解决其冲突(设ts(T)>ts(U))。      T                                U                                 read(b)    read(b)                                                                   write b=b+300   write b=b-500 

解决方案 »

  1.   

    下面的说明是在SQL Server默认的隔离级别下,并且不能在事务生存周期内提示保留共享锁时才能成立的:
    如果两个事务都是在write完毕后立即提交,那么这两个事务应该都是正确的。
    在第一个例子中T先读取b,读完后释放共享锁,然后U又读取b,读完后释放共享锁,接着U改写b,并提交U事务(U事务释放排它锁),最后T改写b,并提交T事务(T事务释放排它锁)。
    在第二个例子中U先读取b,读完后释放共享锁,然后T又读取b,读完后释放共享锁,接着U改写b,并提交U事务(U事务释放排它锁),最后T改写b,并提交T事务(T事务释放排它锁)。
      

  2.   

    接前面的解答:
    在第一个例子中,如果执行T事务的用户重新查询b,会发现b的值没有变,因此该用户会抱怨他的数据除了问题。可以用事件戳解决这个问题,在T和U查询b的时候要把该记录的时间戳一起获取,T查询b时同时获得ts(b),U查询b时同时获得ts(b)。U在改写b时,把自己先前获得的时间戳与记录的实际时间戳比较,发现相等(两者都是ts(b)),于是成功更新纪录,更新的同时把记录的实际时间戳改写为ts(U),而后T进行修改数据前,把自己先前得到的时间戳和记录的实际时间戳比对,发现不相等(一个是ts(b),另一个已经变成了ts(U)了),因此发生更新失败,T需要重新查询以便获得新的时间戳和U新改写的b,然后继续修改数据。
      

  3.   

    在第二个例子中,T和U在查询时同时也获得了ts(b),即数据原有的时间戳,这和第一个例子完全一样,U先更新数据,这时记录的实际时间戳没有变化,和先前一样,U成功更新数据,并把自己的Ts(U)更新到数据库中,T来更新数据,发现自己的时间戳和记录的实际时间戳不相同,因此还是更新失败,T需要重新查询以便获得新的时间戳和U新改写的b,然后继续修改数据。
      

  4.   

    另外需要说明的是如果楼主说的ts(T)和ts(U)代表事务的提交时间的话,那么第一个例子就没法成立了,因为这时U比T先更新数据,而U更新数据后没有提交,是等T事务完成后的某个时间提交的,那么U会一直占有排它锁,而阻止T更新数据,所以T改写数据时将会造成阻塞,T阻塞以后就不可能提交事务了,除非U先于它提交事务,而这和ts(T)<ts(U)是矛盾的。
      

  5.   

    分析的好仔细啊
    学习ing以前在设计的时候从来没考虑时间戳的问题