无死锁的并行合并策略
Parallel merge strategy without deadlock
使用 SQL Server 2016,我希望通过一个包含简单 insert/update/delete 的简单过程将数据从 SourceTable
合并到 DestinationTable
table.
SourceTable
由几个不同的应用程序填充,他们调用 MergeOrders
存储过程将他们上传的行从 SourceTable
合并到 DestinationTable
。
MergeOrders
存储过程 运行 可以有多个并行实例。
我得到很多锁,但这是正常的,问题是有时我得到 "RowGroup deadlocks",这是我负担不起的。
在此并行环境中执行此类合并操作的最佳方式是什么。
我正在考虑 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
此模板中有一些细微之处。首先它没有 catch 块,并且在发生错误时依赖 xact_abort 来释放 applock。并且您希望明确释放应用程序锁,以防在较长 运行ning 事务的上下文中调用此过程。最后,锁的主体设置为 dbo
,这样非 dbo 用户就无法获取冲突锁。这也要求过程是 运行 和 execute as owner
,因为应用程序用户通常不会是 dbo
.
使用 SQL Server 2016,我希望通过一个包含简单 insert/update/delete 的简单过程将数据从 SourceTable
合并到 DestinationTable
table.
SourceTable
由几个不同的应用程序填充,他们调用 MergeOrders
存储过程将他们上传的行从 SourceTable
合并到 DestinationTable
。
MergeOrders
存储过程 运行 可以有多个并行实例。
我得到很多锁,但这是正常的,问题是有时我得到 "RowGroup deadlocks",这是我负担不起的。
在此并行环境中执行此类合并操作的最佳方式是什么。
我正在考虑 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
此模板中有一些细微之处。首先它没有 catch 块,并且在发生错误时依赖 xact_abort 来释放 applock。并且您希望明确释放应用程序锁,以防在较长 运行ning 事务的上下文中调用此过程。最后,锁的主体设置为 dbo
,这样非 dbo 用户就无法获取冲突锁。这也要求过程是 运行 和 execute as owner
,因为应用程序用户通常不会是 dbo
.