spid 상태가 일시 중지된 이유를 확인하는 방법은 무엇입니까?spid가 어떤 리소스를 기다리고 있나요?

StackOverflow https://stackoverflow.com//questions/22038695

문제

난 달린다 EXEC sp_who2 78 그리고 나는 다음을 얻습니다 결과:

results of sp_who2 for spid 78

상태가 정지된 이유를 어떻게 알 수 있나요?

이 과정은 무겁다 INSERT 비용이 많이 드는 쿼리를 기반으로 합니다.큰 SELECT 여러 테이블에서 데이터를 가져와서 다른 테이블에 약 3~4백만 개의 행을 쓰는 것입니다.

잠금/블록이 없습니다.

그만큼 waittype 그것은 에 연결되어 있습니다 CXPACKET.아래 사진에서 볼 수 있듯이 78이 9개 있기 때문에 이해할 수 있습니다.

제가 우려하는 점과 제가 정말로 알고 싶은 점은 왜 1위가 되는지 입니다. SPID 78은 정지되었습니다.

나는 다음과 같은 상황을 이해합니다. SPID 일시 중단되면 프로세스가 리소스를 기다리고 있으며 해당 리소스를 얻으면 다시 시작된다는 의미입니다.

이에 대한 자세한 내용을 어떻게 확인할 수 있나요?무슨 자원?왜 사용할 수 없나요?

저는 아래 코드와 그 변형을 많이 사용하지만, 왜 SPID 정지됐어?

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

도움이 되었습니까?

해결책

정지된:이는 요청이 리소스를 기다리고 있기 때문에 현재 활성 상태가 아니라는 의미입니다.리소스는 페이지 읽기를 위한 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

다른 팁

저는 이러한 종류의 정보를 보기 위해 sp_whoIsActive를 사용합니다. 이는 느린 쿼리 문제를 해결하기 위한 좋은 정보를 제공하는 무료 도구이기 때문입니다.

sp_WhoIsActive를 사용하여 느린 SQL Server 쿼리를 찾는 방법

이를 통해 쿼리 텍스트, 사용 중인 계획, 쿼리가 대기 중인 리소스, 쿼리를 차단하는 항목, 해제 중인 잠금 등을 얻을 수 있습니다.

직접 굴리는 것보다 훨씬 쉽습니다.

다음 방법으로 문제를 해결할 수 있습니다.

  1. 클러스터 인덱스를 수정합니다.
  2. 임시 테이블을 사용하여 전체 테이블의 일부를 가져와 작업합니다.

400,000,000개의 행이 있는 테이블에서 동일한 문제가 있으며 임시 테이블을 사용하여 일부를 가져온 다음 인덱스 변경이 옵션이 아니기 때문에 필터와 내부를 사용합니다.

몇 가지 예:

--
--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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top