什么阻止了“SELECT...WITH(NOLOCK)”?

Ful*_*oof 1 index sql-server index-tuning

在关注 BrentOzar 的“索引重建期间离线多少? ”时,我很好奇运行:

SELECT Quantity FROM [Production].[TransactionHistory]  WITH(NOLOCK)
Run Code Online (Sandbox Code Playgroud)

在执行上述文章中的重建时,观察到它被延迟,直到索引重建完成

什么是阻塞SELECT ... WITH(NO LOCK)以及如何避免它?

更新:
Windows NT 6.1 上 的 Microsoft SQL Server 2012 (SP1) - 11.0.3128.0 (X64)
企业评估版(64 位)(内部版本 7601:Service Pack 1)

Aar*_*and 5

如果重建未指定为ONLINE(除了企业版之外,您不能这样做),则SELECT由于LCK_M_SCH_S而被阻止,如果您执行sp_lock,您将看到它是独占锁。甚至NOLOCK无法穿透。您可以通过以下方式模拟:

  1. 在一个窗口中,启动一项离线重建的事务(这样您就可以在重建之外进行调查,而不是尝试强制进行非常长的重建)。记下 spid:

    USE AdventureWorks2012;
    SELECT @@SPID;
    BEGIN TRANSACTION;
    ALTER TABLE Sales.SalesOrderHeader REBUILD WITH (ONLINE = OFF);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在第二个窗口中,执行NOLOCK查询(再次记下 spid):

    SELECT @@SPID;
    SELECT * FROM Sales.SalesOrderHeader WITH (NOLOCK);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在第三个窗口中,检查:

    SELECT session_id, blocking_session_id, last_wait_type 
      FROM sys.dm_exec_requests 
      WHERE blocking_session_id IN (two spids above)
         OR session_id IN (two spids above);
    
    EXEC sp_lock;
    
    Run Code Online (Sandbox Code Playgroud)

    扫描第二个结果集,查找与主要阻止程序 spid 相关的所有行。

不要忘记回滚或提交...