다른 거래를 차단하는 잠자는 SPID


16

실제로 발생하는 차단을 추적하는 데 문제가 있습니다.

루트 차단 SPID의 상태는 'sleeping'이고 cmd는 'AWAITING COMMAND'이며 sqltextis SET TRANSACTION ISOLATION LEVEL READ COMMITTED입니다.

차단 된 트랜잭션 수별 상위 트랜잭션 보고서를 볼 때 차단 SQL 문은 '-'입니다.

SQL에 대한 추적을 수행했으며 차단이 루트 차단 SPID를 추적 할 때 실제로 어디서나 나를 이끌지 못했습니다. 마지막 추적 명령문은 sqltext위와 동일합니다 SET TRANSACTION ISOLATION LEVEL READ COMMITTED.

TRY / CATCH BEGIN TRAN / COMMIT TRAN / ROLLBACK TRAN 문이 있는지 확인할 수있는 모든 관련 저장 프로 시저를 확인했습니다 (우리는 실행중인 독립 문이 없도록 모든 것에 대해 저장 프로 시저를 사용합니다). 이 문제는 지난 24 시간 동안 발생하기 시작했으며 아무도 시스템을 변경했다고 주장하지 않습니다.

해결책 : 거의 사용되지 않는 저장 프로 시저 중 하나에 삽입 오류 (열 수가 일치하지 않음)가 있었지만 여전히 정확히 무슨 일이 일어나고 있는지 혼란 스럽습니다.

모든 추적 정보를 볼 때이 저장 프로 시저에 대한 EXEC 문이 때때로 나열되었지만 차단 SPID에서 BLOCK이 발생하기 직전에 절대로 없었습니다. 블로킹을 시작할 때 추적이 실행을 기록하지 않은 것 같습니다 (또는 그 안의 명령문 중 하나). 그러나 추적이 실행을 기록하고 차단이 발생하지 않은 다른 시간이 있습니다.

저장 프로 시저 오류 보고서는 사용자가 제공 한 것으로 여러 EXEC 문을 추적하여 SSMS에서 실행할 수있었습니다. 내가 그들을 실행했을 때 우리는 막히지 않았거나 멈추지 않았습니다. 예상대로 실행되었습니다 (캐치 블록이 시작되고 오류가 발생한 후 트랜잭션을 롤백했습니다). 저장 프로 시저 수정을 해결 한 후에도 문제가 다시 나타나지 않습니다.


차단 SPID의 호스트 이름이 전혀 도움이되지 않는다고 가정합니다.
Jon Seigel

아니요, 웹 서버 중 하나의 IP 일뿐입니다. 로그인 / 등록 프로세스 (오류가 발생했다고 생각되는) 동안 각 SPROC 호출에 대한 모든 SQL 로그인을 별도의 사용자 이름으로 변경하는 또 다른 아이디어가 있습니다. 차단을 유발할 수있는 SPROC를 분리하는 데 도움이됩니다.
Brad

1
TRY / CATCH는 컴파일 오류를 포착하지 않으며 일치하지 않는 열 삽입은 컴파일 오류입니다. 이것은 또한 많은 XX : Completed 프로파일 러 이벤트를 트리거하지 않습니다.
Remus Rusanu

1
천재 개발자가 INSERT INTO [table] SELECT * from [othertable]을 사용하고 피어에 걸리지 않았기 때문에 실제로 컴파일 오류가 아닙니다. 3 개의 동시 세션에서 ColdFusion에서 1000 번 개발에 대해 SPROC를 실행했으며 프로덕션에서와 같이 트랜잭션을 열지 않았습니다.
Brad

답변:


10

의견에서, 당신은 SQL 쿼리를 중단 한 클라이언트 측 명령 시간 초과가 있다고 생각합니다. 연결 풀링으로 인해 SQL Server에서 연결이 열려 있기 때문에 트랜잭션을 롤백하지 않습니다.

따라서 SET XACT_ABORT ON을 사용하거나 클라이언트 롤백 코드를 추가해야합니다.

모든 세부 사항 은 SQL Server Transaction Timeout 을 참조하십시오.


모든 SPROC에는 TRY / CATCH 블록과 BEGIN TRAN / COMMIT TRAN / ROLLBACK TRAN 문이 포함되어 있으며 ROLLBACK은 CATCH에 있습니다. XACT_ABORT가 여전히 효과가 있습니까?
Brad

@ 브래드 : 예. 내 링크를 참조하십시오. 캐치 블록은 CommandTimeout에서 히트하지 않습니다
gbn

gbn : 감사합니다. 여전히 혼란 스러워요. 연결이 시간 초과되지 않도록 설정되었습니다 (0). 따라서 연결을 재사용하고 연결이 오류 (TRY / CATCH 및 TRAN 블록이 있음)와 함께 SPROC를 실행하면 CATCH 블록에서 ROLLBACK을 절대 실행할 수 없으므로 테이블을 잠그고 트랜잭션을 유지합니다. 열다? 그건 말이되지 않습니다.
브래드

@Brad : 오류가있는 SPROC가 CATCH 블록에 도달합니다. 나는 달리 말하거나 다르게 말하지 않았다. 그러나 내 링크는 ConnectionTimeout과 다른 CommandTimeout이 있으면 어떻게되는지 알려줍니다. 클라이언트가 "중단"이라고 말하고 SQL Server가 처리를 중지합니다. Ergo, CATCH 블록 또는 롤백 또는 커밋은 절대 발생하지 않습니다
gbn

CommandTimeout이 지정되어 있다고 생각하지 않습니다. 우리의 모든 스토어드 프로시 저는 sqlstress를 사용하여 테스트 중이며 10 명의 사용자 10 회 (최소한) 반복에서 1000ms 미만으로 수행해야합니다. 나는 아직도 일어난 일에 대해 매우 혼란 스럽지만 문제가 발견 된 것으로 질문을 업데이트하고 있습니다.
브래드

9

sys.dm_exec_connections에서 most_recent_sql_handle을 사용하여 마지막으로 실행 된 명령문을보십시오.

SELECT  t.text,
        QUOTENAME(OBJECT_SCHEMA_NAME(t.objectid, t.dbid)) + '.'
        + QUOTENAME(OBJECT_NAME(t.objectid, t.dbid)) proc_name,
        c.connect_time,
        s.last_request_start_time,
        s.last_request_end_time,
        s.status
FROM    sys.dm_exec_connections c
JOIN    sys.dm_exec_sessions s
        ON c.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) t
WHERE   c.session_id = 72;--your blocking spid

또한 해당 spid에 대한 미결 거래가 있는지 확인하십시오.

SELECT  st.transaction_id,
        at.name,
        at.transaction_begin_time,
        at.transaction_state,
        at.transaction_status
FROM    sys.dm_tran_session_transactions st
JOIN    sys.dm_tran_active_transactions at
        ON st.transaction_id = at.transaction_id
WHERE   st.session_id = 72;--your blocking spid

또한 DBCC INPUTBUFFER(spid)마지막으로 실행 된 SQL을 볼 수도 있습니다 .
Mike Fal

나는 그것들을 모두 사용했고 마지막 명령은 항상 원래 게시물에 넣은 것입니다 : SET TRANSACTION ISOLATION LEVEL READ COMMITTED. 또한 DBCC OPENTRAN을 실행했으며 차단 PID에 대한 열린 트랜잭션이 있음을 알 수 있습니다.
Brad

명령문이 실제로 프로 시저의 일부인 경우 첫 번째 선택에서도 프로 시저 이름을 제공합니다.
Sebastian Meine

우리는 우리 웹 서버에서 임시 쿼리를 사용하지 않을 것을 확신하며, WHERE 절이 없어도 첫 번째 쿼리를 실행할 때 소수의 SQL 세션에서만 명명 된 SPROC 만 얻습니다. 나머지 열은 NULL입니다.
Brad

'SET TRANSACTION ISOLATION LEVEL READ COMMITTED'라는 세션이 많이 있으며 모든 세션이 ColdFusion (웹 서버에서 사용되는 기본 스크립팅)에서 나왔습니다. 유휴 상태 일 때 연결을 유지하기 위해 해당 연결을 유지하도록 설정된 상태에서 ColdFusion을 사용했을 수 있습니다.
Brad

4

Adam Machanic의 sp_whoisactive를 사용해 보셨습니까 ? 외부 명령이 실제로 proc 내에 있는지 확인하는 옵션이 있습니다. 응용 프로그램이 트랜잭션을 커밋하는 대신 열려있는 것일 수 있습니다. DBCC OPENTRAN 도 살펴보십시오 .


DBCC OPENTRAN에 감사드립니다. 블로킹 PID에 공개 트랜잭션이 있지만 더 이상 세부 정보가 없다고 알려줍니다. sp_whoisactive는 내가 직접 얻을 수 있었던 것과 같은 정보를 차단 된 프로세스에 반환합니다. 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED'이외의 진행 상황에 대한 자세한 내용은 아직 없습니다.
Brad
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.