我的应用程序运行夜间清除过程,以从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升级为表锁?在我在这张桌子上完全禁用锁定升级之前,我想了解这一点。
答案 0 :(得分:0)
我无法评论您的问题,因为我在这个网站上没有足够的声誉,所以我在这里发表评论。
我在晚上运行清理任务时遇到了类似的问题。删除语句被“GHOST CLEANUP”锁定。 这里看看这个: SQL Server Lock Timeout Exceeded Deleting Records in a Loop
希望这有帮助。 我当时发现的一个奇怪的解决方案是: 1)插入记录以保存在具有相同结构的另一个表中。 (复制) 2)截断表清理 3)插入数据以保持从副本到现在空表。 4)截断复制表以释放空间。
这个技巧比清除本身更快,因为删除是因为截断而在瞬间完成。不知何故,插入的成本比删除成本要便宜。
但是,我仍然建议避免这种解决方案。您还可以将块减少到100到500之间。这会增加清理所需的时间,但您不太可能进行锁升级。