无死锁的并行合并策略

问题描述 投票:0回答:1

使用SQL Server 2016,我希望将数据从一个? SourceTableDestinationTable 与一个简单的过程,其中包含一个简单的插入-更新-删除同一张表。

流程中的 SourceTable 是由几个不同的应用程序来填补的,他们称之为。MergeOrders 存储过程,以合并其上传的行,从 SourceTable 变成 DestinationTable.

可以有几种情况 MergeOrders 存储过程并行运行。

我得到了很多锁,但这是正常的,问题是有时我会得到 "RowGroup死锁",这是我不能承受的。

在这种并行环境下,执行这种合并操作的最好方法是什么。

我在考虑使用TABLOCK或者SERIALIZABLE的提示,也可能是应用锁来序列化访问,但如果有更好的方法,我很感兴趣。

sql-server merge sql-server-2016 database-deadlocks
1个回答
1
投票

一个应用程序锁将序列化试图运行这个过程的会话。 它看起来应该是这样的。

create or alter procedure ProcWithAppLock 
with execute as owner
as
begin
  set xact_abort on;
  set nocount on;
  begin transaction;
  declare @lockName nvarchar(255) = object_name(@@procid) + '-applock';
  exec sp_getapplock @lockName,'Exclusive','Transaction',null,'dbo';


  --do stuff
  waitfor delay '00:00:10';
  select getdate() dt, object_name(@@procid);

  exec sp_releaseapplock @lockName, 'Transaction', 'dbo';
  commit transaction;
end

在这个模板中,有一些微妙的地方。 首先,它没有一个捕获块,而是在出现错误时依靠xact_abort来释放applock。 而你希望明确地释放app锁,以防这个过程在一个较长运行的事务中被调用。 最后将锁的 principal 设置为 dbo 这样就不会有非dbo用户获得一个冲突的锁。 这也要求存储过程在运行时必须使用 execute as owner由于应用程序用户通常不会 dbo.

© www.soinside.com 2019 - 2024. All rights reserved.