日期:2014-05-18  浏览次数:20710 次

关于行锁的问题
我想在select中锁定查询的行,并更新,这是我做的实验
第一个连接
DECLARE @id int BEGIN TRAN
SET @id = 0
  SELECT TOP 1 @id = id
  FROM t_73 WITH (UPDLOCK)
  WHERE teacode1 = '' WAITFOR delay '00:00:03' IF @id > 0 BEGIN
  UPDATE t_73
  SET teacode1 = '1'
  WHERE id = @id 
 END COMMIT

第二个连接
DECLARE @id int BEGIN TRAN
SET @id = 0
  SELECT TOP 1 @id = id
  FROM t_73 WITH (UPDLOCK)
  WHERE teacode1 = '' WAITFOR delay '00:00:03' IF @id > 0 BEGIN
  UPDATE t_73
  SET teacode1 = '2'
  WHERE id = @id 
 END COMMIT

执行完第一个连接马上执行第2个,总是只能更新1行,请高手给我看看应该怎么修改。

------解决方案--------------------
SQL code
WAITFOR  time '10:53:00'

------解决方案--------------------
up
------解决方案--------------------
WITH (UPDLOCK,HOLDLOCK) --加多一个锁保留到事务完成

------解决方案--------------------
执行完第一个连接马上执行第2个,总是只能更新1行

当你的事务提交以后你的锁自然就释放了,不可能说你更新了一行,那么这一行永远都保留更新信息的,你自己想想这样也不合理


SQL code
--整理一下,发代码别偷懒
DECLARE   @id   int   
BEGIN   TRAN 
  SET   @id   =   0 
  SELECT   TOP   1   @id   =   id 
    FROM   t_73   WITH    (UPDLOCK,HOLDLOCK) 
   WHERE   teacode1   =   ' '   

  WAITFOR   delay   '00:00:03 '   
  IF   @id   >   0   
  BEGIN 
    B on C

------解决方案--------------------
是不合理,


SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

begin tran

select * from tablename with (rowlock) where id=3

waitfor delay '00:00:05'

commit tran




------解决方案--------------------
关注
------解决方案--------------------
这样的结果是正确的.

在用这些锁之前要了解这些锁的作用,UPDLOCK一般是可用来防止丢失更新.
UPDLOCK 
读取表时使用更新锁,而不使用共享锁,并将锁一直保留到语句或事务的结束。UPDLOCK 的优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。

在第一个连接中执行
SELECT TOP 1 @id = id 
FROM t_73 WITH (UPDLOCK) 
WHERE teacode1 = ' '
就等于告诉服务器"我将要更新teacode1 = ' ' 的记录,所有在这条语句后所发出的更新语句(即第二个连接的UPDLOCK语句处)都必须等待,也就是这两个连接是第一个事物执行完后,第二个才开始. 
当第一个连接执行完了,teacode1 = 1,接着在第二个连接(UPDLOCK)处开始执行,满足teacode1 = ' '的记录没有.所以只有第一个连接更新了.
 
------解决方案--------------------
测试过了,你自己的代码可以实现你的需求啊.
------解决方案--------------------
DECLARE @id int
BEGIN TRAN 
SET @id = 0 
SELECT TOP 1 @id = id 
FROM t_73 WITH (UPDLOCK,READPAST) --加上readpast
WHERE teacode1 = ' '
 
WAITFOR delay '00:00:10 '
IF @id > 0
BEGIN 
PRINT(@id)
UPDATE t_73 SET teacode1 = convert(varchar(10),id)
WHERE id = @id
end

commit tran

执行后出现死锁(发生位置在Update处),为什么会这样呢,其实在这里我们忽略了索引对并发的影响.
在id上建立个索引就可以避免死锁了.