SQL Server锁定问题

时间:2015-06-08 14:44:43

标签: sql-server sql-server-2008-r2

我遇到了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'独特"记录代码。

问题

  1. 这些锁和锁的数量是否只是这种类型的正常SQL操作加载?
  2. 在我们开始使用的UPDATE中,子查询导致的问题多于TOP(1)吗?我正在尝试确认我可以删除ORDER BY语句并删除额外的处理步骤。
  3. 不同的索引会有帮助吗?我想知道索引更新是否可能是最初锁定的原因,但现在我不确定。
  4. 是否有更好或更有效的方法来获取唯一的RowID?
  5. WITH(ROWLOCK)导致更多锁定而不是关闭它会导致吗?这个想法是ROWLOCK只会锁定1个特定记录,并允许另一个proc更新另一个记录并选择而不锁定表或页面。
  6. 为了测试任何可能的解决方案,有没有人有他们推荐的任何工具来进行压力测试并同时运行100个查询?
  7. 对所有问题感到抱歉,只是为了确保我对我们的流程和我们提出的问题尽可能清楚。

    提前感谢任何见解,因为这对我们来说是一个非常令人沮丧的问题。

    硬件

    我们在具有24 GB RAM的双Xeon CPU上运行SQL Server 2008 R2。所以我们应该有足够的马力来完成这个过程。

1 个答案:

答案 0 :(得分:0)

看起来问题的最佳解决方案是创建一个带有标识的单独表,并使用插入中的@@IDENTITY来确定要处理的下一行。到目前为止,我的压力测试解决了所有锁定问题。感谢所有指出我正确方向的人!