ORDER BY和UPDLOCK-A(非)工作示例

时间:2011-06-21 08:57:47

标签: sql-server-2005 locking

虽然我无法透露有关真实表格的信息(如果我可以,但我会)导致上一个问题中描述的问题,我从头开始构建了一个(非)工作示例,它准确地再现了数据类型 - 类型,列大小按列大小)我面临的问题。所以我创建了一个名为“QueueTest”的新数据库并运行以下脚本:

CREATE TABLE Request
(
    RequestID   BIGINT PRIMARY KEY,
    Priority    TINYINT,
    DateEntered DATETIME
)

CREATE TABLE Options
(
    RequestIDRef    BIGINT PRIMARY KEY,
    SomeOptions     NVARCHAR(MAX)
)

ALTER TABLE Options ADD

    CONSTRAINT FK_REQUESTIDREF FOREIGN KEY ( RequestIDRef ) REFERENCES [Request] ( RequestID )

GO

INSERT INTO Request VALUES ( 1, 2, GETDATE() )
INSERT INTO Request VALUES ( 2, 1, GETDATE() )
INSERT INTO Request VALUES ( 3, 3, GETDATE() )
INSERT INTO Request VALUES ( 4, 2, GETDATE() )

INSERT INTO Options VALUES ( 1, 'Options1' )
INSERT INTO Options VALUES ( 2, 'Options2' )
INSERT INTO Options VALUES ( 3, 'Options3' )
INSERT INTO Options VALUES ( 4, 'Options4' )

CREATE NONCLUSTERED INDEX IX_OPTIONS_REQUESTIDREF ON [Options] ( RequestIDRef )
CREATE NONCLUSTERED INDEX IX_REQUEST_PRIORITY_DATEENTERED ON [Request] ( Priority , DateEntered ) INCLUDE ( RequestID )

之后我打开了两个新查询Query1Query2,并运行以下脚本来模拟问题:

BEGIN TRANSACTION

SELECT TOP 2 RequestID FROM ( Request R WITH ( ROWLOCK , UPDLOCK , READPAST ) INNER JOIN Options O WITH ( ROWLOCK , UPDLOCK , READPAST ) ON ( R.RequestID = O.RequestIDRef ) ) ORDER BY Priority ASC , DateEntered ASC

WAITFOR DELAY '00:00:02.500'

COMMIT TRANSACTION

我得到的结果是

Query1 | Query 2
   2   |
   1   |
当然,我当时正在等待

Query1 | Query 2
   2   |    4
   1   |    3

所以,我假设即使我有上述索引,Query1仍然锁定整个表。以下是两个查询的执行计划:

执行计划

StmtText
-----------------------
SET SHOWPLAN_TEXT ON

(1 row(s) affected)

StmtText
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

BEGIN TRANSACTION

SELECT TOP 2 RequestID FROM ( Request R WITH ( ROWLOCK , UPDLOCK , READPAST ) INNER JOIN Options O WITH ( ROWLOCK , UPDLOCK , READPAST ) ON ( R.RequestID = O.RequestIDRef ) ) ORDER BY Priority ASC , DateEntered ASC

(2 row(s) affected)

StmtText
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  |--Top(TOP EXPRESSION:((2)))
       |--Nested Loops(Inner Join, WHERE:([QueueTest].[dbo].[Options].[RequestIDRef] as [O].[RequestIDRef]=[QueueTest].[dbo].[Request].[RequestID] as [R].[RequestID]))
            |--Index Scan(OBJECT:([QueueTest].[dbo].[Request].[IX_REQUEST_PRIORITY_DATEENTERED] AS [R]), ORDERED FORWARD)
            |--Clustered Index Scan(OBJECT:([QueueTest].[dbo].[Options].[PK__Options__5366EEE80BC6C43E] AS [O]))

(4 row(s) affected)

StmtText
---------------------------------

WAITFOR DELAY '00:00:02.500'

COMMIT TRANSACTION

(2 row(s) affected)

请注意,当我使用SET SHOWPLAN_TEXT ON运行两个查询时,我认为WAITFOR DELAY指令未得到遵守 - 事实上,第一个查询立即完成,所以当我运行第二个查询时它已经完成。

导致锁定问题的原因是什么?请帮助我,因为我自己无法想象它。

修改:请注意,我无法使用SELECT TOP 2指令创建视图。这里的2仅用于说明目的,而在实际情况下,它是传递给存储过程的参数,然后运行此SELECT。另请注意,使用

创建索引视图
SET QUOTED_IDENTIFIER ON
GO

ALTER VIEW TestView WITH SCHEMABINDING AS

    SELECT RequestID , Priority , DateEntered FROM( dbo.Request R INNER JOIN dbo.Options O ON ( R.RequestID = O.RequestIDRef ) )

GO

CREATE UNIQUE CLUSTERED INDEX IX_TESTE_1 ON TestView ( RequestID )
CREATE NONCLUSTERED INDEX IX_TESTE_2 ON TestView ( Priority ASC , DateEntered ASC ) INCLUDE ( RequestID )

然后从TestView WITH ( ROWLOCK , UPDLOCK , READPAST )中选择也不起作用,无论有没有ORDER BY子句。

1 个答案:

答案 0 :(得分:1)

你有一个“聚集索引扫描”和一个“索引扫描”,它阻止了两个表中的所有行正如我在之前的回答中所说的那样。

同样来自之前的答案:

  1. 使用索引视图
  2. 视图
  3. 中没有提示
  4. 调用视图时添加NOEXPAND提示
  5. 最后,索引IX_REQUEST_PRIORITY_DATEENTERED没有JOIN条件。这可能会删除其中一个扫描

    如果你不听上面的“查看”位,那么试试这两个

    CREATE NONCLUSTERED INDEX IX_REQUEST_PRIORITY_DATEENTERED ON [Request]
      (RequestID , Priority , DateEntered )
    
    
    CREATE NONCLUSTERED INDEX IX_REQUEST_PRIORITY_DATEENTERED ON [Request]
      (Priority , DateEntered , RequestID )