arv*_*man 5 sql sql-server multithreading
我有一个基于键执行更新插入的合并语句。(为简单起见,我们将其称为 RefId)。这是为了确保表是唯一的RefId. 然而,在生产中,我们有多个服务器使用这个存储过程插入到这个表中,如果两个服务器以非常接近的间隔使用相同的 RefId 插入,则会发生重复(即 2 次插入)而不是 1 次插入和更新。我相信这是因为,SQL 服务器锁定了新插入的行,而另一个称为存储过程的并行无法检测到它的存在。MERGE 语句不支持 NoLock,因此我看不到明显的解决方法。我已经使用多个线程(而不是服务器)模拟了并行插入,并且在这种情况下偶尔也会发生重复。除了对数据库强制执行唯一约束(我无法控制的原因)之外,还有什么方法可以让我的 upsert 在并发情况下按预期工作?
这是存储的过程(当插入更新以合理的时间差进行时它可以正常工作,但在并行情况下会失败)
WITH UniqueData AS
( SELECT * FROM
( SELECT *, rank() over ( PARTITION BY RefId ) AS UniqueRank
FROM @Data
) AS Ranked WHERE UniqueRank=1
)
MERGE MyTable AS destination
USING UniqueData AS source
ON ( destination.RefId = source.RefId)
WHEN NOT MATCHED THEN
INSERT (RefId, Miles,UpdateUTC)
VALUES( source.RefId, source.Miles, getutcdate())
WHEN MATCHED THEN
UPDATE SET
destination.Miles = ISNULL(source.Miles , destination.Miles ),
destination.UpdateUTC = getutcdate()
Run Code Online (Sandbox Code Playgroud)
您可以使用 WITH (HOLDLOCK)
...
MERGE MyTable WITH (HOLDLOCK) AS destination
...
Run Code Online (Sandbox Code Playgroud)
您可以在此处阅读详细信息:http : //weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
| 归档时间: |
|
| 查看次数: |
1202 次 |
| 最近记录: |