最佳实践:SQL SP序列化执行

时间:2018-04-20 12:32:26

标签: sql sql-server-2012 locking deadlock

我们有一个SP,在插入行后执行。它会更新事务中的多个表,但在某些情况下,当插入多行并且SP同时执行时 - 它会遇到死锁。我们试图优化它,并降低了陷入僵局的机会 - 但无法避免它。

现在我们尝试了另一种方式(此SP在事务中运行):

DECLARE @padLock         INT

BEGIN TRY

EXEC @padLock = sp_getapplock @Resource='mytable_modify', @LockMode='Exclusive', @LockOwner='Transaction';

IF @padLock < 0 
   THROW 99888, 'Lock named [mytable_modify] cannot be acquired.', 1

...
do some stuff which might cause deadlock
...
EXEC sp_releaseapplock @Resource = 'mytable_modify', @LockOwner='Transaction';

END TRY
BEGIN CATCH
   SELECT 
       @strErrMsg = ERROR_MESSAGE() + 
                       'Line:' + CONVERT(varchar(5), ERROR_LINE()),
       @intErrSeverity = ERROR_SEVERITY(),
       @intErrState = ERROR_STATE();

  if @padLock >= 0  
    EXEC sp_releaseapplock @Resource = 'mytable_modify', @LockOwner='Transaction';

    RAISERROR(@strErrMsg,   -- Message text.
                @intErrSeverity,  -- Severity.
                @intErrState      -- State
                );
END CATCH;

这是好的做法,还是我们还有麻烦?

1 个答案:

答案 0 :(得分:0)

获取课程粒度锁(在此处使用sp_getapplock)将避免死锁,但会以并发性和吞吐量为代价。

我不会把它称为一个好习惯,但我发现sp_getapplock在特殊情况下是一个可接受的解决方案,否则无法轻易避免死锁,并且所得到的单线程性能是可以接受的为你的工作量。如果“做一些事情”花费几毫秒,除非你需要维持每秒数百的速度,否则可能没有性能问题。