使用SQL Server 2016,我希望将数据从一个? SourceTable
到 DestinationTable
与一个简单的过程,其中包含一个简单的插入-更新-删除同一张表。
流程中的 SourceTable
是由几个不同的应用程序来填补的,他们称之为。MergeOrders
存储过程,以合并其上传的行,从 SourceTable
变成 DestinationTable
.
可以有几种情况 MergeOrders
存储过程并行运行。
我得到了很多锁,但这是正常的,问题是有时我会得到 "RowGroup死锁",这是我不能承受的。
在这种并行环境下,执行这种合并操作的最好方法是什么。
我在考虑使用TABLOCK或者SERIALIZABLE的提示,也可能是应用锁来序列化访问,但如果有更好的方法,我很感兴趣。
一个应用程序锁将序列化试图运行这个过程的会话。 它看起来应该是这样的。
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
.