2012-04-11 24 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

相關問題