SQL Server 锁升级

Posted

技术标签:

【中文标题】SQL Server 锁升级【英文标题】:SQL Server lock escalation 【发布时间】:2015-03-11 14:36:18 【问题描述】:

我的应用程序每晚运行一个清除过程,以从我的 OLTP 应用程序的主表中删除旧记录。我在清除过程中遇到锁升级,它阻止并发插入到表中,因此我修改了清除过程以循环并删除 4900 块中的记录,这应该远低于 SQL Server 的锁升级阈值 5000。虽然锁升级大大减少了,SQL Server Profiler 仍然在循环中的以下 DELETE 语句上报告偶尔的锁升级:

-- outer loop increments @BatchMinId and @BatchMaxId variables
  BEGIN TRAN

  -- limit is set at 4900
  DELETE TOP (@limit) h
  OUTPUT DELETED.ChildTable1Id,
         DELETED.ChildTable2Id,
         DELETED.ChildTable3Id,
         DELETED.ChildTable4Id
  INTO #ChildRecordsToDelete
  FROM MainTable h WITH (ROWLOCK)
  WHERE h.Id >= @BatchMinId AND h.Id <= @BatchMaxId AND h.Id < @MaxId AND 
        NOT EXISTS (SELECT 1 FROM OtherTable ot WHERE ot.Id = h.Id);

  -- delete from ChildTables 1-4 (no additional references to MainTable)
  COMMIT TRAN;
-- end loop

SQL Server Profiler 中报告的锁升级事件(应该是escalated lock count)的“IntegerData2”列范围从 10197 到 10222,看起来不接近 4900 的任何倍数(我的清除批量大小)加上 1250 的任意倍数 (number of additional locks SQL Server may take before attempting escalation)。

鉴于我明确地将 DELETE 语句限制为 4900 行,如何获得更多的锁,尤其是 SQL Server 升级为表锁的程度?在我完全禁用此表上的锁升级之前,我想了解这一点。

【问题讨论】:

我不会禁用锁升级 - 它可能会导致其他问题。有关禁用锁升级的非常清晰的讨论,请参阅sqlpassion.at/archive/2014/02/25/lock-escalations 以 1000 的批量大小进行清除怎么样?根据我的经验,您不会看到主要的速度差异。 我认为,尽管您尽了最大的努力,SQL Server 可能会在选择升级锁时决定升级锁。删除是否有及时性要求?从逻辑上讲,批量越小,锁升级的可能性就越小。还能再减吗?此外,无论如何都可以调整查询 - 这可能会降低锁定升级的可能性。 我不是这方面的专家,但如果你有非聚集索引,我认为这些索引也需要锁定和删除 + 可能还有聚集索引中的一些页面。这可以解释吗? @benjaminmoskovits 我将禁用锁升级仅作为最后的手段。我可以尝试减小批量大小,但即使这样可行,我也想了解为什么比锁升级阈值小 100 还不够好,但比锁升级阈值小 4000 就足够了。 @DanSaunders 据我了解,SQL Server 可能会将锁升级推迟到每个对象超过 5000 个锁,但它可能不会任意升级到少于 5000 个锁。 【参考方案1】:

由于我在此网站上没有足够的声誉,因此无法对您的问题发表评论,所以我在这里发表评论。

我在夜间运行的清理任务中遇到了类似的问题。删除语句被“GHOST CLEANUP”锁定。 这里看看这个: SQL Server Lock Timeout Exceeded Deleting Records in a Loop

希望对您有所帮助。 我当时发现的一个奇怪的解决方案是: 1)插入记录以保存在另一个具有相同结构的表中。 (复制) 2) 截断表进行清理 3) 将要从副本中保留的数据插入到现在为空的表中。 4) 截断复制表以释放空间。

这个技巧比删除本身更快清理,因为删除是在瞬间完成的,因为截断。不知何故,插入成本比删除成本低。

但是,我仍然建议避免使用此解决方案。您还可以将块减少到 100 到 500 之间。这会增加清理所需的时间,但锁升级的可能性较小。

【讨论】:

以上是关于SQL Server 锁升级的主要内容,如果未能解决你的问题,请参考以下文章

sql server 2005 2709 出错 是啥意思

当多个对象持有一个共享锁并且一个想要升级到独占时,sql中基于锁的并发控制如何工作?

sql server2008升级到2008 R2出现问题

MySQL innoDB 中的锁升级

在SQL Server里我们为什么需要意向锁(Intent Locks)?

SQL SERVER 2008 升级至SQL SERVER 2012