2011-12-02 119 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”会怎么样?它会帮助锁定数据(如果它不存在)? –

相关问题