2012-04-11 50 views
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. 

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

目标是

  1. ,这个存储过程的多个实例可以在同一时间运行和处理的记录自己的“共享”,以实现最大的并发。
  2. 的存储过程的执行不应该对以前运行等那么仍在执行

我不认为重复读可以帮助在这里,因为它不会阻止新的记录与“未处理的值“正在阅读(请纠正我,如果我错了)。

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

,我看到的一个解决办法是,在proc的每次运行产生了自己独特的GUID并分配给标志,但不知何故,我想我模拟的东西,SQL服务器已经可以解决的开箱。

是让每次运行一个sproc进程的唯一途径,它是将这些行“共享”到SERIALIZABLE中?

问候,汤姆

+0

一个答案为[使用表作为队列](HTTP ://stackoverflow.com/questions/4686726/sql-server-using-a-table-as-a-queue)可能会帮助你。 – AakashM 2012-04-11 14:45:43

回答

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 
+0

非常优雅的解决方案。我希望我们的prod sql server支持输出,因为它是在后来的某些sql server版本AFAIK – buckley 2012-04-11 14:39:16

+0

@buckley中引入的它在2005年推出。 – 2012-04-11 14:50:01

相关问题