如何解决存储过程中的SQLServer锁定表
你们之间回答了我的问题。我要发表自己的答复,以整理我发表在一篇文章中的工作解决方案。关键似乎是事务处理方法,在last_auto_id表上具有锁定提示。将事务隔离设置为可序列化似乎会产生死锁问题。
这就是我所得到的(已编辑以显示完整的代码,因此希望我可以得到更多的答案…):
DECLARE @Pointer AS INT
BEGIN TRANSACTION
-- Check what the next ID to use should be
SELECT @NextId = LastId + 1 FROM Last_Auto_Id WITH (TABLOCKX) WHERE Name = 'CustomerNo'
-- Now check if this next ID already exists in the database
IF EXISTS (SELECT CustomerNo FROM Customer
WHERE ISNUMERIC(CustomerNo) = 1 AND CustomerNo = @NextId)
BEGIN
-- The next ID already exists - we need to find the next lowest free ID
CREATE TABLE #idtbl ( IdNo int )
-- Into temp table, grab all numeric IDs higher than the current next ID
INSERT INTO #idtbl
SELECT CAST(CustomerNo AS INT) FROM Customer
WHERE ISNUMERIC(CustomerNo) = 1 AND CustomerNo >= @NextId
ORDER BY CAST(CustomerNo AS INT)
-- Join the table with itself, based on the right hand side of the join
-- being equal to the ID on the left hand side + 1. We're looking for
-- the lowest record where the right hand side is NULL (i.e. the ID is
-- unused)
SELECT @Pointer = MIN( t1.IdNo ) + 1 FROM #idtbl t1
LEFT OUTER JOIN #idtbl t2 ON t1.IdNo + 1 = t2.IdNo
WHERE t2.IdNo IS NULL
END
UPDATE Last_Auto_Id SET LastId = @NextId WHERE Name = 'CustomerNo'
COMMIT TRANSACTION
SELECT @NextId
这将在事务开始时取出排他表锁,然后该表锁成功地将所有其他请求排队,直到此请求更新了表并提交了它的事务之后。
我编写了一些C代码,以将其与来自六个会话的并发请求一起使用,并且运行良好。
但是,我确实有个担心,那就是锁定“提示”一词-有人知道sqlServer是将其视为确定的指令还是仅作为提示(即,它可能不会始终服从它吗?)。
解决方法
我有一张桌子,我需要在99%的时间内自动分配ID(其他1%似乎使用身份列来排除)。因此,我有一个存储过程来获取以下行中的下一个ID:
``
select @nextid = lastid+1 from last_auto_id
check next available id in the table...
update last_auto_id set lastid = @nextid
检查必须检查用户是否手动使用了ID并找到下一个未使用的ID。
当我依次调用它并返回1、2、3时,它可以正常工作。我需要做的是在多个进程同时调用此方法的情况下提供一些锁定。理想情况下,我只需要它专用于围绕此代码锁定last_auto_id表,以便第二个调用必须等待第一个调用更新表才能运行它的select。
在Postgres中,我可以执行类似“ LOCK TABLE last_auto_id;”的操作 显式锁定表。有什么想法如何在SQL
Server中完成它吗?
提前致谢!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。