1

我正在维护一个存储过程,开发人员已经实现了他自己的锁定机制,但对我来说它似乎有缺陷:

CREATE PROCEDURE Sproc 1
AS

Update X
set flag = lockedforprocessing
where flag = unprocessed

-- Some processing occurs here with enough time to 
-- 1. table X gets inserted new rows with a flag of unprocessed
-- 2. start another instance of this Sproc 1 that executes the above update

Select from X
where flag = lockedforprocessing

-- Now the above statement reads rows that it hadn't put a lock on to start with.

我知道我可以将它 sproc 包装在一个隔离级别为 SERIALIZABLE 的事务中,但我想避免这种情况。

目标是

  1. 该 sproc 的多个实例可以同时运行并处理它们自己的“共享”记录以实现最大并发性。
  2. sproc 的执行不应等待仍在执行的先前运行

我认为 REPEATABLE READ 在这里没有帮助,因为它不会阻止读取值为“未处理”的新记录(如果我错了,请纠正我)。

我刚刚发现了 sp_getlock 存储过程,它可以解决错误,但序列化精确,这不是我的目标。

我看到的一个解决方案是让 proc 的每次运行都生成自己唯一的 GUID 并将其分配给标志,但不知何故我认为我正在模拟 SQL Server 已经可以开箱即用的解决方案。

让 sproc 的每次运行处理它的“共享”行的唯一方法是让它在 SERIALIZABLE 中?

问候,汤姆

4

1 回答 1

0

假设 X 中有一个 ID 字段,更新 X 的临时表可以提供帮助:

CREATE PROCEDURE Sproc 1
AS
-- Temporary table listing all accessed Xs
   declare @flagged table (ID int primary key)
-- Lock and retrieve locked records
   Update X
      set flag = lockedforprocessing
   output Inserted.ID into @flagged
    where flag = unprocessed

-- Processing
   Select from X inner join @flagged f on x.ID = f.ID

-- Clean-up
   update X
      set flag = processed
     from x inner join @flagged f on x.ID = f.ID
于 2012-04-11T13:51:54.480 回答