2011-12-02 172 views
3

我在SQL服務器ASP頁存儲會話變量與下面的存儲過程:什麼可能導致主鍵異常?

CREATE PROCEDURE [dbo].[MyProcedure] 
     @sessionId varchar(512), 
     @variable varchar(350), 
     @value image 
AS 
BEGIN 
     BEGIN TRAN 
       DECLARE @result int = 0; 
       DECLARE @locked bit; 

       IF (SELECT COUNT(*) FROM Sessions WHERE id = @sessionId) = 0 
       BEGIN 
         SET @result = -1; 
       END 
       ELSE BEGIN 
         DELETE Variables WHERE sessionId = @sessionId AND variable = @variable 
         IF @value IS NOT NULL 
         BEGIN 
           INSERT Variables VALUES(@sessionId, @variable, @value, 0) 
         END             
       END  
    COMMIT TRAN 
    RETURN @result 
END 

但是,一旦在一段時間,我得到一個主鍵異常(消息2627):「PRIMARY KEY約束的衝突‘PK_Variables’ 。不能在對象'dbo.Variables'中插入重複鍵「。 注意:沒有涉及觸發器。

謝謝!

+0

我們可以有表格變量的結構嗎?您的變量主鍵是否自動增加? – bAN

回答

2

假設您的PK位於sessionId,variable,那麼同時執行存儲過程的@sessionId,@variable可以執行此操作。

兩者併發執行

DELETE Variables WHERE sessionId = @sessionId AND variable = @variable 

行,然後都前進到insert

這隻有在sessionId,variable組合沒有預先存在的記錄時纔會發生,因爲DELETE會被阻塞。

+0

但是BEGIN/COMMIT並不妨礙這個?如果不是,我該如何鎖定記錄(不必鎖定整個表格)?感謝您的時間 –

+0

@JorgitoGutierrez - 當記錄不存在時,無需鎖定。你需要'serializable'隔離級別或等效的鎖定提示來鎖定範圍,但是當前行爲有什麼問題?如果你有兩個同時執行''sessionid,變量'',那麼它會是非常隨意的哪一個「勝利」,所以爲什麼不讓這個失敗者提出PK違規而不是阻止它,因此它立即覆蓋其他執行? –

+0

我現在對如何實現解決方案感到困惑......我從未使用過可序列化的隔離。如果我做了「SELECT * FROM WHERE sessionId = @sessionId AND variable = @variable」會怎麼樣?它會幫助鎖定數據(如果它不存在)? –

相關問題