简体   繁体   English

SQL Server锁定问题

[英]Trouble with SQL Server locks

I am running into an issue where SQL Server is causing a significant number of locks (95 to 150) on our main table. 我遇到了一个问题,SQL Server在我们的主表上导致了大量的锁(95到150)。 They are typically short duration locks, lasting under 3 seconds, but I would like to eliminate those if I possibly can. 它们通常持续时间很短,持续时间不超过3秒,但我想尽可能消除它们。 We have also noticed that typically there are no blocks, but occasionally we have a situation where the blocks seem to "cascade" and then the entire system slows down considerably. 我们还注意到通常没有块,但偶尔我们会遇到块似乎“级联”然后整个系统大幅减速的情况。

Background 背景

We have up to 600 virtual machines processing data and we loaded a table in SQL so we could monitor any records that got stalled and records that were marked complete. 我们有多达600个虚拟机处理数据,我们在SQL中加载了一个表,因此我们可以监控任何停滞的记录和标记为完整的记录。 We typically have between 200,000 and 1,000,000 records in this table during our processing. 在我们的处理过程中,我们通常在此表中有200,000到1,000,000条记录。

What we are trying to accomplish 我们正在努力实现的目标

We are attempting to get the next available record (Status = 0). 我们正在尝试获取下一个可用记录(Status = 0)。 However, since there can be multiple hits on the stored proc simultaneously, we are trying to make sure each VM gets a unique record. 但是,由于存储过程可能会同时存在多个命中,因此我们尝试确保每个VM都获得唯一的记录。 This is important because processing takes between 1.5 and 2.5 minutes per record and we want to make this as clean as possible. 这很重要,因为每条记录的处理时间需要1.5到2.5分钟,我们希望尽可能保持干净。

Our thought process to this point 我们的思维过程到此为止

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

This update was causing us a few issues with locks, so we re-worked the process a little bit and changed the where to a sub-query to return the top 1 RowID (primary key) from the table. 这个更新导致了一些锁的问题,所以我们稍微重新处理了一下这个过程,并改变了子查询的位置,从表中返回前1个RowID(主键)。 This seemed to help things run a little bit smoother, but then we occasionally get over-loaded in the database again. 这似乎有助于事情运行得更顺畅,但随后我们偶尔会在数据库中过载。

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)

We discovered that having a significant number of Status 1 and 2 records int he table causes slowdowns. 我们发现在表中有大量的状态1和2记录会导致速度减慢。 We figured it was from a table scan on the Status column. 我们认为它是来自Status列的表扫描。 We added the following index but it did not help solve the locks. 我们添加了以下索引,但它没有帮助解决锁。

CREATE NONCLUSTERED INDEX IX_Test_Status_RowID
ON [dbo].[Test] ([Status])
INCLUDE ([RowID])

The final step after the UPDATE, we use the RowID returned to select out the details: 在UPDATE之后的最后一步,我们使用返回的RowID来选择细节:

SELECT 'Test' as FileName, *, @Nick as [Nickname] 
FROM Test WITH (NOLOCK)
WHERE RowID IN (SELECT id from @retValue)

Types of locks 锁的类型

The majority of the blocks are LCK_M_U and LCK_M_S, which I would expect with that UPDATE and SELECT query. 大多数块都是LCK_M_U和LCK_M_S,我期望UPDATE和SELECT查询。 We did have 1 or 2 LCK_M_X locks as well occasionally. 我们偶尔也有1或2个LCK_M_X锁。 That made me think we may still be getting collisions on our "unique" record code. 这让我觉得我们可能仍然会在我们的“独特”记录代码上发生冲突。

Questions 问题

  1. Are these locks and the number of locks just normal SQL operations for this type load? 这些锁和锁的数量是否只是这种类型的正常SQL操作加载?
  2. Is the sub-query causing more issues than a TOP(1) in the UPDATE we started with? 在我们开始的UPDATE中,子查询是否导致了比TOP(1)更多的问题? I am trying to get confirmation I can remove the ORDER BY statement and remove that extra step of processing. 我试图得到确认我可以删除ORDER BY语句并删除额外的处理步骤。
  3. Would a different index help? 不同的指数会有帮助吗? I wondered if the index updating was a possible cause of the locks initially, but now I am not sure. 我想知道索引更新是否是最初锁定的可能原因,但现在我不确定。
  4. Is there a better or more efficient way to get a unique RowID? 是否有更好或更有效的方法来获得唯一的RowID?
  5. Is the WITH (ROWLOCK) causing more locks than leaving it off would cause? WITH(ROWLOCK)导致更多的锁而不是关闭它会导致吗? The idea is ROWLOCK would only lock the 1 specific record and allow another proc to update another record and select without locking the table or page. 想法是ROWLOCK只会锁定1个特定记录并允许另一个proc更新另一个记录并选择而不锁定表或页面。
  6. Does anyone have any tools they recommend to stress test and run 100 queries simultaneously in order to test any potential solutions? 有没有人有他们推荐的任何工具来进行压力测试并同时运行100个查询以测试任何可能的解决方案?

Sorry for all the questions, just trying to make sure I am as clear as possible on our process and the questions we have. 对不起所有的问题,只是为了确保我对我们的流程和我们提出的问题尽可能清楚。

Thanks in advance for any insight as this is a really frustrating issue for us. 提前感谢任何见解,因为这对我们来说是一个非常令人沮丧的问题。

Hardware 硬件

We are running SQL Server 2008 R2 on a Dual Xeon CPU with 24 GB of RAM. 我们在具有24 GB RAM的双Xeon CPU上运行SQL Server 2008 R2。 So we should have plenty of horsepower for this process. 所以我们应该有足够的马力来完成这个过程。

It looks like the best solution to the issue was to create a separate table with an identity and use the @@IDENTITY from the insert to determine the next row to process. 看起来问题的最佳解决方案是创建一个带有标识的单独表,并使用插入中的@@IDENTITY来确定要处理的下一行。 That has solved all my lock issues so far in my stress testing. 到目前为止,我的压力测试解决了所有锁定问题。 Thanks to all who pointed my in the right direction! 感谢所有指出我正确方向的人!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM