代码之家  ›  专栏  ›  技术社区  ›  Marcello Miorelli

如何找出蜘蛛的状态被暂停的原因?蜘蛛在等待什么资源?

  •  46
  • Marcello Miorelli  · 技术社区  · 12 年前

    我跑了 EXEC sp_who2 78 我得到以下信息 results :

    results of sp_who2 for spid 78

    我如何找到其状态被暂停的原因?

    这个过程很沉重 INSERT 基于昂贵的查询。一个大的 SELECT 它从多个表中获取数据,并将大约3-4百万行写入不同的表。

    没有锁/块。

    这个 waittype 它链接到 CXPACKET 我可以理解,因为你可以在下面的图片上看到有9个78。

    令我担忧的是,我真正想知道的是 SPID 78被暂停。

    我知道当 蜘蛛 挂起时,表示进程正在等待资源,当它获得资源时将继续。

    我怎样才能找到更多的细节?什么资源?为什么它不可用?

    我使用了很多下面的代码及其变体,但我还能做什么来找出为什么 蜘蛛 是否暂停?

    select * 
    from sys.dm_exec_requests r
    join sys.dm_os_tasks t on r.session_id = t.session_id
    where r.session_id = 78
    

    我已经用过了 sp_whoisactive 。我得到的这个特定spid78的结果如下:(分成3张图片以适应屏幕)

    enter image description here

    3 回复  |  直到 6 年前
        1
  •  57
  •   Marcello Miorelli    11 年前

    暂停的: 这意味着请求当前未处于活动状态,因为它正在等待资源。资源可以是用于读取页面的I/O,WAIT可以是网络上的通信,或者它正在等待锁定或锁存。它将在等待的任务完成后变为活动状态。例如,如果查询发布了读取完整表tblStudents的数据的I/O请求,则此任务将暂停,直到I/O完成。一旦I/O完成(内存中有tblStudents表的数据),查询将进入RUNNABLE队列。

    因此,如果它正在等待,请检查wait_type列以了解它正在等待什么,并根据wait_time进行故障排除。

    我开发了以下过程来帮助我,它包括WAIT_TYPE。

    use master
    go
    
    CREATE PROCEDURE [dbo].[sp_radhe] 
    
    AS
    BEGIN
    
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    
    SELECT es.session_id AS session_id
    ,COALESCE(es.original_login_name, '') AS login_name
    ,COALESCE(es.host_name,'') AS hostname
    ,COALESCE(es.last_request_end_time,es.last_request_start_time) AS last_batch
    ,es.status
    ,COALESCE(er.blocking_session_id,0) AS blocked_by
    ,COALESCE(er.wait_type,'MISCELLANEOUS') AS waittype
    ,COALESCE(er.wait_time,0) AS waittime
    ,COALESCE(er.last_wait_type,'MISCELLANEOUS') AS lastwaittype
    ,COALESCE(er.wait_resource,'') AS waitresource
    ,coalesce(db_name(er.database_id),'No Info') as dbid
    ,COALESCE(er.command,'AWAITING COMMAND') AS cmd
    ,sql_text=st.text
    ,transaction_isolation =
        CASE es.transaction_isolation_level
        WHEN 0 THEN 'Unspecified'
        WHEN 1 THEN 'Read Uncommitted'
        WHEN 2 THEN 'Read Committed'
        WHEN 3 THEN 'Repeatable'
        WHEN 4 THEN 'Serializable'
        WHEN 5 THEN 'Snapshot'
    END
    ,COALESCE(es.cpu_time,0) 
        + COALESCE(er.cpu_time,0) AS cpu
    ,COALESCE(es.reads,0) 
        + COALESCE(es.writes,0) 
        + COALESCE(er.reads,0) 
        + COALESCE(er.writes,0) AS physical_io
    ,COALESCE(er.open_transaction_count,-1) AS open_tran
    ,COALESCE(es.program_name,'') AS program_name
    ,es.login_time
    FROM sys.dm_exec_sessions es
        LEFT OUTER JOIN sys.dm_exec_connections ec ON es.session_id = ec.session_id
        LEFT OUTER JOIN sys.dm_exec_requests er ON es.session_id = er.session_id
        LEFT OUTER JOIN sys.server_principals sp ON es.security_id = sp.sid
        LEFT OUTER JOIN sys.dm_os_tasks ota ON es.session_id = ota.session_id
        LEFT OUTER JOIN sys.dm_os_threads oth ON ota.worker_address = oth.worker_address
        CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS st
    where es.is_user_process = 1 
      and es.session_id <> @@spid
    ORDER BY es.session_id
    
    end 
    

    下面的查询还可以显示spid挂起时的基本信息,显示spid正在等待的资源。

    SELECT  wt.session_id, 
        ot.task_state, 
        wt.wait_type, 
        wt.wait_duration_ms, 
        wt.blocking_session_id, 
        wt.resource_description, 
        es.[host_name], 
        es.[program_name] 
    FROM  sys.dm_os_waiting_tasks  wt  
    INNER  JOIN sys.dm_os_tasks ot ON ot.task_address = wt.waiting_task_address 
    INNER JOIN sys.dm_exec_sessions es ON es.session_id = wt.session_id 
    WHERE es.is_user_process =  1 
    

    请参见下图作为示例:

    enter image description here

        2
  •  15
  •   steoleary    10 年前

    我使用sp_whoIsActive查看这类信息,因为它是一个现成的免费工具,可以为您提供疑难解答慢速查询的良好信息:

    How to Use sp_WhoIsActive to Find Slow SQL Server Queries

    通过这个,您可以获得查询文本、它正在使用的计划、查询正在等待的资源、阻塞它的是什么、它正在取出的是什么锁等等。

    比自己动手容易得多。

        3
  •  0
  •   Moises Conejo    9 年前

    您可以通过以下方式解决:

    1. 修复集群索引。
    2. 使用时态表获取所有表的一部分并使用它。

    我对一个有40000000行的表也有同样的问题,我使用临时表来获取其中的一部分,然后我使用过滤器和inner,因为更改索引不是一个选项。

    例如:

    --
    --this is need be cause DECLARE @TEMPORAL are not well for a lot of data.
    CREATE TABLE #TEMPORAL
    (
        ID BIGINT,
        ID2 BIGINT,
        DATA1 DECIMAL,
        DATA2 DECIMAL
    );
    
    WITH TABLE1 AS
    (
        SELECT
            L.ID,
            L.ID2,
            L.DATA
        FROM LARGEDATA L
        WHERE L.ID = 1
    ), WITH TABLE2 AS
    (
        SELECT
            L.ID,
            L.ID2,
            L.DATA
        FROM LARGEDATA L
        WHERE L.ID = 2
    ) INSERT INTO #TEMPORAL SELECT
        T1.ID,
        T2.ID,
        T1.DATA,
        T2.DATA
    FROM TABLE1 T1
        INNER JOIN TABLE2 T2
            ON T2.ID2 = T2.ID2;
    --
    --this take a lot of resources proces and time and be come a status suspend, this why i need a temporal table.
    SELECT
        *
    FROM #TEMPORAL T
    WHERE T.DATA1 < T.DATA2
    --
    --IMPORTANT DROP THE TABLE.
    DROP TABLE #TEMPORAL