2013-07-13 52 views
1

我寫了多線程應用程序,每一個線程調用SQL Server的過程。我需要保護一排由多個線程得到我想要的每一行把它只能使用一個線程我用這個代碼:我該如何運行一次按時程序?

CREATE PROCEDURE GetRow 
    @ThreadID int 
AS 
BEGIN 

    DECLARE @rowID int; 
    SELECT TOP (1) @rowID=[ID] FROM [TestTable] WHERE [ThreadID] = 0 (AND some other parameters) 

    IF @rowID is not NULL 
    BEGIN 
     UPDATE TOP (1) [TestTable] SET [CallCount] = [CallCount]+1,[ThreadID] = @ThreadID WHERE [ID] = @rowID 

    --some other codes 

    END 
END 

正如我所說我運行的應用程序,然後我的應用程序創建10個線程和我設置threadid只有一個線程,但我看到一行被超過1個線程調用和約4-5個線程得到一個排..我怎麼能這樣做最好的方式,我解決了這個代碼,我不喜歡有兩個相同的地方在選擇和更新:

CREATE PROCEDURE GetRow 
    @ThreadID int 
AS 
BEGIN 

    DECLARE @rowID int; 

    UPDATE TOP (1) [TestTable] SET [CallCount] = [CallCount]+1,[ThreadID] = @ThreadID WHERE [ThreadID] = 0 (AND some other parameters) 


    SELECT TOP (1) @rowID=[ID] FROM [TestTable] WHERE [ThreadID] = @ThreadID (AND some other parameters) 

    IF @rowID is not NULL 
    BEGIN 

    --some other codes 

    END 
END 

我如何用頂級代碼做到這一點?我應該先更新,然後選擇像上面的代碼修復它?

+1

你想達到什麼目的?我試圖理解,但我沒有得到它... – jazzytomato

+0

@Thomas Haratyk對不起,我真的試圖解釋它..我不想在多個線程中選擇特殊行..我寫程序更新theardid列行'噸讓其他線程選擇,但在Sametime中其他線程選擇它的.. –

回答

2

如果你使用SQL Server 2005或更高版本,你是能夠使用新的OUTPUT clausecombine the UPDATE and SELECT

不過我建議備份和思考你的數據庫架構,以及它是否真正適合你的問題 - 尤其是在多線程!

我得到的印象是你想計算來自每個線程的調用。將每個電話號碼INSERT連成一個簡單的ThreadCallCount表,只需要一個ThreadID列即可。每個電話都是一個新的行。稍後,您可以通過ThreadID此表Sum()獲得每個線程的總調用次數。這將是簡單和容易的,以確保它是線程安全的。

這聽起來像有你想找回一些其他的數據,而當它被存儲如何/目前還不清楚。但類似的分析 - 更簡單的表格 - 可能會幫助你。

一般來說:不要覺得你需要擠在同一個表。使用多線程將有助於將事情分解成更小的部分。隨意使用更多的表格,每個表格都有一個明確的目的。 SQL Server旨在安全高效地處理行事務,因此儘可能地利用它。

+0

tanx很多爲解釋和我使用'sql server 2008 r2'我給你upvote和我喜歡你的插入方法的通話計數,所以我沒有得到比你更好的答案,我接受你的答案,並tanx再次傢伙(你和編碼器) –

+1

偉大的建議格雷格。 Id僅添加[sp_getAppLock](http://msdn.microsoft.com/zh-cn/library/ms189823。aspx)也是序列化存儲過程調用的有用方法。如果存儲過程有時很難使其他線程等待:) –

1

我會建議寫作THEAD安全的代碼而不是做在存儲過程中。

你沒有提到你的編碼語言,C#中的一種方式是包裝調用內部lock塊這個存儲過程的代碼:

using System.Threading 
... 

public class ClassName { 

    object syncLock = new object(); 
    ... 

    SomeFunction(){ 

     lock(syncLock){ 

      // For example, com could be SqlCommand object that calls stored procedure 
      int updatedRowCount = com.ExecuteNonQuery(); 
      ... 
     } 
    } 

} 
+0

坦我給你給予好評,但真的我喜歡來解決它的SQL不是C# –

+0

我同意編碼器,這將是最好的處理C#中的線程安全性(或任何你正在使用的)。但是,如果您更喜歡在SQL級別上執行此操作,或者因爲您無法依賴應用程序代碼來實現線程安全性 - 我以這種方式發佈了答案。 –

相關問題