UPDLOCK后T-SQL函数不是线程安全的

时间:2015-10-05 21:21:22

标签: sql-server multithreading tsql

我有一个简单的getNextID过程,它检索表中的id值并将值递增1.它是在考虑到一些多线程的情况下构建的,但看起来程序中的UPDLOCK实际上并没有它按预期线程安全,我试图了解原因。这个想法是初始选择期间的UPDLOCK会阻止任何其他线程执行该选择,直到程序底部的更新完成为止;然而,这似乎并非如此,因为当两个线程同时触发时我得到重复值。

在阅读了一些其他线程之后,我认为可能发生的事情是UPDLOCK阻止其他线程更新行,但它并不阻止它们执行之前的初始选择更新。因此两个线程都执行相同的select(检索相同的值),然后线程2正在等待线程1更新,然后线程2将该行更新为相同的值。我理解锁正在做什么吗?完成防线程的正确方法是将它全部包装在BEGIN / COMMIT TRANSACTION中吗?

var $select = $("#my_input").selectize();
var selectize = $select[0].selectize;
selectize.setValue(selectize.search("My Default Value").items[0].id);

谢谢!

1 个答案:

答案 0 :(得分:1)

另一种方法是稍微使用不同版本的更新查询,并显然将整个事务转换为事务。

CREATE PROCEDURE getNextID
     @NextNumber INT          OUTPUT
    ,@id_type    VARCHAR(20)
AS
BEGIN
  SET NOCOUNT ON;

    DECLARE @NextValue TABLE (NextNumber int);

BEGIN TRANSACTION;

    UPDATE its_id_sequence
      SET last_used_number = ISNULL(@NextNumber, 0) + 1
     OUTPUT inserted.last_used_number INTO @NextValue(NextNumber)
    WHERE id_type = @id_type

    SELECT @NextNumber = NextNumber FROM @NextValue

COMMIT TRANSACTION;

END

因此,您首先更新而不读取值,并在更新后获取值并使用它。