SQL函数在UPDLOCK之后不是线程安全的

我有一个简单的getNextID过程,它在表中检索一个id值,并将值递增1.它是在考虑了一些多线程的情况下构建的,但似乎该过程中的UPDLOCK实际上并没有像过去那样使线程安全意图和我试图理解为什么。 这个想法是,初始选择期间的UPDLOCK会阻止任何其他线程执行该选择,直到该过程底部的更新完成; 但是,这似乎并不是这种情况,因为当两个线程同时触发时,我得到重复值。

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

 CREATE PROCEDURE getNextID (
    @NextNumber int OUTPUT
    ,@id_type VARCHAR(20)
    )
AS
BEGIN

    SELECT @NextNumber = (last_used_number + 1)
    FROM its_id_sequence WITH (UPDLOCK)
    WHERE id_type = @id_type

    UPDATE its_id_sequence
    SET last_used_number = @NextNumber
    WHERE id_type = @id_type
END

谢谢!


另一种方法是略微使用不同版本的更新查询,并明显将整个事件变为事务。

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

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

链接地址: http://www.djcxy.com/p/32845.html

上一篇: SQL function not thread safe after UPDLOCK

下一篇: What is a scope of a table hint lock?