asc*_*99c 8 sql sql-server locking
我有一个表,我需要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中完成它?
提前致谢!
更新后,将lastid增加1,并在单个事务中将此值分配给本地变量.
编辑
感谢Dave和Mitch指出原始解决方案的隔离级别问题.
UPDATE last_auto_id WITH (READCOMMITTEDLOCK)
SET @nextid = lastid = lastid + 1
Run Code Online (Sandbox Code Playgroud)
你们之间已经回答了我的问题。我正在添加自己的回复,以整理我在一篇文章中得到的工作解决方案。关键似乎是事务方法,在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
Run Code Online (Sandbox Code Playgroud)
这会在事务开始时取出独占表锁,然后成功地将任何进一步的请求排队,直到该请求更新表并提交其事务之后。
我编写了一些 C 代码来处理来自六个会话的并发请求,并且它工作得很好。
然而,我确实有一个担心,那就是术语锁定“提示” - 有谁知道 SQLServer 是否将其视为明确的指令或只是一个提示(即也许它不会总是遵守它??)
归档时间: |
|
查看次数: |
26696 次 |
最近记录: |