测试用的 表跟存储过程很简单
表  test   num(int)
CREATE PROCEDURE [dbo].[wcs] AS 
begin
DECLARE @NEXT_VALUE INT;
begin tran
update test set [num]=num+1
select @NEXT_VALUE=num from test WITH (UPDLOCK) 
select @NEXT_VALUE
commit tran
当多个客户端 大量调用存储过程时  假如同时执行 update 那句 会不会死锁 
另外加了更新锁 能不能避免 @NEXT_VALUE 返回值重复  

解决方案 »

  1.   

    现在的写法可能会死锁,也不能避免 @NEXT_VALUE 返回值重复
    写法有几个问题
    1、事务放在这里控制不了,应该在调用这个存储过程前开事务,在处理(可能插入包括返回单号的单据数据)后结束事务才有防止重复好产生的效果
    2、更新锁 不够,应该用排它锁,而且用保持锁
    3、应该第一个语句就加锁
      

  2.   

    首先谢谢您很详细的回答 
    1 事务为什么放到这里 不起作用 ?是要放到客户端 调用 存储过程 时加事务吗?存储过程改为这样
    CREATE PROCEDURE [dbo].[wcs] AS 
    begin
    DECLARE @NEXT_VALUE INT;
    --begin tran
    select @NEXT_VALUE=num from test WITH (XLOCK) 
    update test set [num]=num+1
    select @NEXT_VALUE
    --commit tran
    可以吗  ?
      

  3.   

    我是在不解   当同一时间 执行 select @NEXT_VALUE=num from test WITH (XLOCK)是 会发生死锁还是 因为用了 xlock 而消除了死锁 那 updlock 同时执行呢  思维混乱了  updlock  与  xlock 根本区别再哪里
      

  4.   

    如果就你这么一个简单的update不会造成死锁的
    不过你的select查询出的数据倒是可能重复,可以用update set直接赋值
    update test set [num]=num+1,@NEXT_VALUE=num+1
      

  5.   


    通过代码猜测一下,test应该就1行数据,用来取序列号的,用#5的方法是最好,无需显式事务。你这样封装也无妨,死锁不会,而且select也不需要额外加锁,update持有的X锁会保持到事务结束,也就不会有重复。updlock是用来序列化更新操作的,xlock排它锁顾名思义了。
      

  6.   

    1楼说 是有死锁可能 的 
    如果按照 5楼的方法 根本就不用select了   update 本身就是排他锁吧 所以也没有死锁的可能了 
    重复值也不会出现了  ?  如此这类问题就解决了 ?事务也用了吧 
      

  7.   

    也就是说  即使同时间 执行  update 语句   数据库引擎自动加xlock 根本不用担心 死锁的可能是吧 
      

  8.   

    死锁是两个不同事务互相请求对方资源而导致的无限期的等待
    你的update语句只获得当前的唯一一个数据,不会去请求其他资源,
    所以不会出现无限期的等待,但是由于并发情况是会产生正常的锁等待,
    正常的锁等待只是延迟,不会产生死锁,这样解释明白不?
      

  9.   

    还要看你的默认事务隔离级别是什么,有些隔离级别即使是SELECT都要持有锁,到事务结束,有些只需要在SELECT语句完毕(可能后续还有语句)就释放。锁的持有时间也会导致死锁。