sql-server – 高效的事务,记录锁定

前端之家收集整理的这篇文章主要介绍了sql-server – 高效的事务,记录锁定前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个存储过程,它选择1条记录.可以从不同PC上的几个不同应用程序调用存储过程.这个想法是存储过程带回了需要处理的下一条记录,如果两个应用程序同时调用存储过程,则不应该返回相同的记录.我的查询如下,我正在尝试尽可能高效地编写查询(sql 2008).它可以比这更有效地完成吗?
  1. CREATE PROCEDURE GetNextUnprocessedRecord
  2. AS
  3. BEGIN
  4. SET NOCOUNT ON;
  5.  
  6. --ID of record we want to select back
  7. DECLARE @iID BIGINT
  8.  
  9. -- Find the next processable record,and mark it as dispatched
  10. -- Must be done in a transaction to ensure no other query can get
  11. -- this record between the read and update
  12. BEGIN TRAN
  13.  
  14. SELECT TOP 1
  15. @iID = [ID]
  16. FROM
  17. --Don't read locked records,only lock the specific record
  18. [MyRecords] WITH (READPAST,ROWLOCK)
  19. WHERE
  20. [Dispatched] is null
  21. ORDER BY
  22. [Received]
  23.  
  24. --Mark record as picked up for processing
  25. UPDATE
  26. [MyRecords]
  27. SET
  28. [Dispatched] = GETDATE()
  29. WHERE
  30. [ID] = @iID
  31.  
  32. COMMIT TRAN
  33.  
  34. --Select back the specific record
  35. SELECT
  36. [ID],[Data]
  37. FROM
  38. [MyRecords] WITH (NOLOCK,READPAST)
  39. WHERE
  40. [ID] = @iID
  41.  
  42. END

解决方法

使用READPAST锁定提示是正确的,您的sql看起来没问题.

添加使用XLOCK虽然也是HOLDLOCK / SERIALIZABLE

  1. ...
  2. [MyRecords] WITH (READPAST,ROWLOCK,XLOCK)
  3. ...

这意味着您获得了ID,并在您继续并更新它时专门锁定该行.

编辑:在Dispatched和Received列上添加索引以使其更快.如果[ID](我认为它是PK)没有聚集,则INCLUDE [ID].并过滤索引,因为它是sql 2008

你也可以使用这个结构,它可以在没有XLOCK或HOLDLOCK的情况下一次完成

  1. UPDATE
  2. MyRecords
  3. SET
  4. --record the row ID
  5. @id = [ID],--flag doing stuff
  6. [Dispatched] = GETDATE()
  7. WHERE
  8. [ID] = (SELECT TOP 1 [ID] FROM MyRecords WITH (ROWLOCK,READPAST) WHERE Dispatched IS NULL ORDER BY Received)

UPDATE,assign,set in one

猜你在找的MsSQL相关文章