【问题标题】:Fixing upsert issue with TRANSACTION ISOLATION LEVEL REPEATABLE READ?修复事务隔离级别可重复读取的 upsert 问题?
【发布时间】:2011-12-10 12:49:42
【问题描述】:

我有一个执行更新的 SQL 语句,然后如果 @@ROWCOUNT 为 0,它将插入。这基本上是 SQL 2008 中的MERGE。我们遇到了两个线程同时更新失败的情况。它将尝试在表中两次插入相同的键。我们使用的是默认事务隔离级别,已提交读。将级别更改为可重复读取会解决此问题,还是我必须一直到 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;";

【问题讨论】:

  • 在 Read Committed Transaction Isolation 级别不会出现脏读。您只能通过未提交的读取来获得脏读。
  • 抱歉的意思是 - 使更新和插入原子。我如何组合它们

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


【解决方案1】:

您需要一直到SERIALIZABLE

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-14
    • 2017-07-06
    • 2020-04-04
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    相关资源
    最近更新 更多