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