【问题标题】:How to check blocking queries in SQL Server如何检查 SQL Server 中的阻塞查询
【发布时间】:2017-04-25 23:55:39
【问题描述】:

我有一个仓库服务器,它从旧系统 24/7 获取数据/同步,我注意到我的一些报告/sql 作业性能不确定,并且大多数时候我从 DBA 团队听说我的 查询被阻塞 到其他同步进程。

我从 DBA 团队了解到命令,即 EXEC SP_WHO2,通过它我可以通过查看 BlkBy 列来识别导致阻塞的查询 spid。

请建议我如何避免阻塞以及在 SQL Server

中检查 blocking 的其他方法

【问题讨论】:

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


    【解决方案1】:

    还有一个有用的查询。此查询将为您提供有关阻塞会话 ID、时间(从阻塞会话运行时开始)、执行查询、正在执行此阻塞会话的用户帐户的重要详细信息。当您处理有许多用户运行他们的事务的生产环境并且您应该找出阻塞会话和用户并采取必要的措施时,该查询非常有用。

    SELECT
    [s_tst].[session_id],
    [s_es].[login_name] AS [Login Name],
    DB_NAME (s_tdt.database_id) AS [Database],
    [s_tdt].[database_transaction_begin_time] AS [Begin Time],
    [s_tdt].[database_transaction_log_bytes_used] AS [Log Bytes],
    [s_tdt].[database_transaction_log_bytes_reserved] AS [Log Rsvd],
    [s_est].text AS [Last T-SQL Text],
    [s_eqp].[query_plan] AS [Last Plan]
    FROM
    sys.dm_tran_database_transactions [s_tdt]
    JOIN
    sys.dm_tran_session_transactions [s_tst]
    ON
    [s_tst].[transaction_id] = [s_tdt].[transaction_id]
    JOIN
    sys.[dm_exec_sessions] [s_es]
    ON
    [s_es].[session_id] = [s_tst].[session_id]
    JOIN
    sys.dm_exec_connections [s_ec]
    ON
    [s_ec].[session_id] = [s_tst].[session_id]
    LEFT OUTER JOIN
    sys.dm_exec_requests [s_er]
    ON
    [s_er].[session_id] = [s_tst].[session_id]
    CROSS APPLY
    sys.dm_exec_sql_text ([s_ec].[most_recent_sql_handle]) AS [s_est]
    OUTER APPLY
    sys.dm_exec_query_plan ([s_er].[plan_handle]) AS [s_eqp]
    ORDER BY
    [Begin Time] ASC;
    GO
    

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
    【解决方案2】:

    This 是一本非常全面的指南。不过有一些基本准则:

    • 避免使用SELECT ... INTO #temp 模式,而是先创建一个表并使用INSERT INTO #Temp SELECT...
    • 在可以容忍dirty reads 的查询上使用WITH (NOLOCK)
    • 确保proper indexes存在
    • WHERE 子句中使用sargable 谓词
    • 与您的 DBA 讨论可能启用READ_COMMITTED_SNAPSHOT 隔离级别

    【讨论】:

      【解决方案3】:

      除了 Sp_Who2,您还可以使用以下查询来识别 SQL 中的阻塞。

      SELECT
      db.name DBName,
      tl.request_session_id,
      wt.blocking_session_id,
      OBJECT_NAME(p.OBJECT_ID) BlockedObjectName,
      tl.resource_type,
      h1.TEXT AS RequestingText,
      h2.TEXT AS BlockingTest,
      tl.request_mode
      FROM sys.dm_tran_locks AS tl
      INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id
      INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address
      INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id
      INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id
      INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id
      CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
      CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
      GO
      

      还可以使用以下命令检查特定 SPID 的详细信息。

      DBCC INPUTBUFFER(56) — Will give you the Event Info.
      
      KILL 56 -- Will kill the session of this id.
      

      【讨论】:

      • 感谢您的快速周转,这很有帮助。
      • 可以在 SQL 授权 blog post 上查看此例程的详细说明。完成警告/注意事项
      • 很好,但如果我们可以用 DBCC INPUTBUFFER 中的信息替换 RequestingText/BlockingTest 会更好
      猜你喜欢
      • 1970-01-01
      • 2011-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多