让每个sproc进程运行它的行份

时间:2012-04-11 13:26:18

标签: sql-server tsql transactions locking

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

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.

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

目标是

  1. 这个sproc的多个实例可以同时运行并处理它们自己的“共享”记录,以实现最大的并发性。
  2. 执行sproc时不应等待仍在执行的上一次运行
  3. 我认为REPEATABLE READ在这里没有帮助,因为它不会阻止读取值为“未处理”的新记录(如果我错了请纠正我)。

    我刚刚发现了sp_getlock sproc,它会解决这个bug但序列化exaction,这不是我的目标。

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

    让每个sproc进程运行的唯一方法就是“共享”行以将其设置为SERIALIZABLE吗?

    问候,汤姆

1 个答案:

答案 0 :(得分: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