我遇到了SQL Server在主表上导致大量锁(95到150)的问题。它们通常持续时间很短,持续时间不超过3秒,但我想尽可能消除它们。我们也注意到通常没有块,但偶尔我们会遇到块似乎是“级联”的情况。然后整个系统大大减慢了。
背景
我们有多达600个虚拟机处理数据,我们在SQL中加载了一个表,因此我们可以监控任何停滞的记录和标记为完整的记录。在处理过程中,我们通常在此表中有200,000到1,000,000条记录。
我们正在努力实现的目标
我们正在尝试获取下一个可用记录(Status = 0)。但是,由于存储过程可能会同时存在多个命中,因此我们尝试确保每个VM都获得唯一的记录。这很重要,因为每条记录的处理时间需要1.5到2.5分钟,我们希望尽可能保持干净。
到目前为止我们的思维过程
UPDATE TOP (1) dbo.Test WITH (ROWLOCK)
SET Status = 1,
VMID = @VMID,
ReadCount = ReadCount + 1,
ProcessDT = GETUTCDATE()
OUTPUT INSERTED.RowID INTO @retValue
WHERE Status = 0
此更新导致了一些锁定问题,因此我们稍微重新处理了该过程,并将子地址查询的位置更改为从表中返回前1个RowID(主键)。这似乎有助于事情运行得更顺畅,但随后我们偶尔会在数据库中过载。
UPDATE TOP (1) dbo.Test WITH (ROWLOCK)
SET Status = 1,
VMID = @VMID,
ReadCount = ReadCount + 1,
ProcessDT = GETUTCDATE()
OUTPUT INSERTED.RowID INTO @retValue
-- WHERE Status = 0
WHERE RowID IN (SELECT TOP 1 RowID FROM do.Test WHERE Status = 0 ORDER BY RowID)
我们发现在表格中有大量的状态1和2记录会导致速度减慢。我们认为它是来自Status列的表扫描。我们添加了以下索引,但它没有帮助解决锁。
CREATE NONCLUSTERED INDEX IX_Test_Status_RowID
ON [dbo].[Test] ([Status])
INCLUDE ([RowID])
UPDATE之后的最后一步,我们使用返回的RowID来选择细节:
SELECT 'Test' as FileName, *, @Nick as [Nickname]
FROM Test WITH (NOLOCK)
WHERE RowID IN (SELECT id from @retValue)
锁类型
大多数块都是LCK_M_U和LCK_M_S,我期望UPDATE和SELECT查询。我们偶尔也有1或2个LCK_M_X锁。这让我觉得我们可能仍然会在我们的'34'独特"记录代码。
问题
对所有问题感到抱歉,只是为了确保我对我们的流程和我们提出的问题尽可能清楚。
提前感谢任何见解,因为这对我们来说是一个非常令人沮丧的问题。
硬件
我们在具有24 GB RAM的双Xeon CPU上运行SQL Server 2008 R2。所以我们应该有足够的马力来完成这个过程。
答案 0 :(得分:0)
看起来问题的最佳解决方案是创建一个带有标识的单独表,并使用插入中的@@IDENTITY
来确定要处理的下一行。到目前为止,我的压力测试解决了所有锁定问题。感谢所有指出我正确方向的人!