sp_getapplock是否会导致SQL Server性能问题?

时间:2018-04-25 20:14:33

标签: sql-server stored-procedures locking

我有一个无法同时执行的存储过程。多个进程调用此存储过程,但进程按顺序访问存储过程至关重要。

存储过程基本上扫描表以查找满足各种条件的主键,将记录标记为调用进程正在使用,然后将主键传递回调用进程。

根据存在的工作量,可能存在一到十几个调用过程的实例。

我决定在存储过程中使用sp_GetAppLock来防止并发。我获取了一个独占事务锁,@Resource设置为仅在此存储过程中使用的字符串。此锁定唯一阻止的是执行此存储过程。

存储过程中的调用如下所示:

     sp_getapplock @Resource='My Unique String Here' 
         ,@LockMode='Exclusive'  -- Type of lock
         ,@LockOwner='Transaction' -- Transaction or Session
         ,@LockTimeout = 5000

它可以游泳。如果我的进程的十几个实例正在运行,则只有其中一个实例在任何一个时间点执行存储过程,而另外一个实例排队并等待轮到他们。

唯一的问题是我们的DBA。他是一名非常优秀的DBA,他不断监视数据库的阻塞情况,并在超过某个阈值时收到警报。我对sp_getapplock的使用触发了很多警报。我的DBA声称阻止内在和自身是一个性能问题。

他的说法准确吗?我的感觉是,这是“好”阻止,因为唯一被阻止的是执行存储过程,并且想要被阻止。但我的DBA表示,强制SQL Server强制执行此阻止是一种重要的资源消耗。

我可以告诉他“按下裂缝管”,就像我们常说的那样吗?或者我应该重新编写我的应用程序以避免需要sp_getapplock

我在sp_getapplock上看到的卖给我的文章在这里:sp_getapplock

2 个答案:

答案 0 :(得分:1)

不幸的是,我认为你的DBA有一点,阻塞会耗尽资源,而这种类型的阻塞会给服务器带来额外的负担。

让我解释一下:

  1. Proc被调用,SQL Server将工作线程从线程池分配给它,它开始执行。

  2. 调用2,3,4,...进来,SQL Server再次为这些调用分配工作线程,线程开始执行,但由于你获得了独占锁,所有线程都被挂起并坐着在"Waiting List"中获取资源。

  3. 由于您的进程,正在保留任何SQL Server上数量非常有限的工作线程。

  4. 现在SQL Server正在积累等待,因为开发人员决定这样做。

  5. 作为一名DBA,我们希望您来SQL Server获取所需内容并尽快保留。如果你故意呆在那里并持有资源并使SQL Server承受压力,那么它会让DBA感到厌烦。

    我认为您需要重新考虑您的应用程序设计并提出替代解决方案。

    可能是SQL Server中的“进程表”,当进程启动时为每个调用更新一个值,并在触发该proc的下一个调用之前先检查进程表。因此,等待事件发生在应用程序层中,并且只有在资源可用时才会转到数据库。

答案 1 :(得分:1)

存储过程基本上是在表中扫描满足各种条件的主键,将记录标记为正在由调用过程使用,然后将主键传递回调用过程。
这是在SP中执行此操作的另一种方法:

BEGIN TRANSACTION
 SELECT x.PKCol
   FROM dbo.[myTable] x WITH (FASTFIRSTROW XLOCK ROWLOCK READPAST)
  WHERE x.col1 = @col1...

 IF @@ROWCOUNT > 0 BEGIN
    UPDATE dbo.[myTable]
       SET ...
     WHERE x.col1 = @col1
 END

COMMIT TRANSACTION

XLOCK 指定在事务完成之前要获取并保持排他锁。如果使用ROWLOCK,PAGLOCK或TABLOCK指定,则排他锁适用于适当的粒度级别。