使用TRANSACTION ISOLATION LEVEL REPEATABLE READ修复upsert问题?

时间:2011-10-18 23:47:04

标签: sql-server sql-server-2005 transactions isolation-level

我有一个执行更新的SQL语句,然后如果@@ROWCOUNT为0,它将插入。这基本上是SQL 2008中的MERGE。我们遇到两个线程同时在更新上失败的情况。它将尝试在表中插入两次相同的密钥。我们正在使用默认事务隔离级别Read Committed。将级别更改为可重复读取是否可以解决此问题,或者我是否必须一直使用Serializable来使其工作?这是一些代码:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

BEGIN TRAN;                                            
UPDATE TableA
SET Duration = @duration              
WHERE keyA = @ID
AND keyB = @IDB;

IF @@rowcount = 0
BEGIN

INSERT INTO TableA (keyA,keyB,Duration) 
VALUES (@ID,@IDB,@duration); 

END
COMMIT TRAN;

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;";

1 个答案:

答案 0 :(得分:2)

你需要一直到SERIALIZABLE

REPEATABLE READ下如果该行不存在,则两个UPDATE语句可以同时运行而不会相互阻塞,并继续执行插入操作。在SERIALIZABLE下,该行的范围将被阻止。

但您还应考虑将隔离级别保留为默认read committed并在keyA,keyB上设置唯一约束,以便插入欺骗的任何尝试都会失败并显示错误。