교착 상태 선택 / 삽입


10

이 인스턴스는 SharePoint 2007 데이터베이스 (SP)를 호스팅합니다. SP 컨텐츠 데이터베이스 내에서 많이 사용되는 하나의 테이블에 대해 수많은 SELECT / INSERT 교착 상태가 발생했습니다. 관련 리소스를 좁혔습니다. 두 프로세스 모두 비 클러스터형 인덱스에 대한 잠금이 필요합니다.
INSERT에는 SELECT 리소스에 대한 IX 잠금이 필요하고 SELECT에는 INSERT 리소스에 대한 S 잠금이 필요합니다. 교착 상태 그래프는 1) SELECT (생산자 / 소비자 병렬 스레드)에서 2 개, 그리고 2) INSERT에서 3 개의 자원을 보여줍니다.
검토를 위해 교착 상태 그래프를 첨부했습니다. 이것은 Microsoft 코드 및 테이블 구조이므로 변경할 수 없습니다.
그러나 MSFT SP 사이트에서 MAXDOP 인스턴스 수준 구성 옵션을 1로 설정하는 것이 좋습니다.이 인스턴스는 다른 많은 데이터베이스 / 응용 프로그램간에 공유되므로이 설정을 비활성화 할 수 없습니다.


따라서 이러한 SELECT 문이 병렬 처리되지 않도록 시도하기로 결정했습니다. 이것이 해결책이 아니라 문제 해결에 도움이되는 임시 수정 사항이라는 것을 알고 있습니다. 따라서 교착 상태가 사라지더라도 (워크로드가 자주 선택 / 삽입) 워크로드가 변경되지 않더라도“병렬 처리 비용 임계 값”을 표준 25에서 40으로 늘 렸습니다. 내 질문은 왜?

SPID 356 INSERT에는 비 클러스터형 인덱스에 속하는 페이지에 IX 잠금이 있습니다.
SPID 690 SELECT 실행 ID 0은 동일한 비 클러스터형 인덱스에 속하는 페이지에 S 잠금이 있습니다.

지금

SPID 356은 SPID 690 리소스에 대한 IX 잠금을 원하지만 SPID 356이 SPID 690 실행 ID 0에 의해 차단되고 있기 때문에이를 유지할 수 없습니다. SP 잠금
690 실행 ID 1은 SPID 356 리소스에 대한 S 잠금을 원하지만 SPID 690 실행 ID로 인해이를 얻을 수 없습니다. 1은 SPID 356에 의해 차단되었으며 이제 교착 상태가 발생했습니다.

SkyDrive에서 실행 계획을 찾을 수 있습니다.

전체 교착 상태 세부 사항은 여기에서 찾을 수 있습니다

누군가 내가 왜 그것을 정말로 감사하게 이해하는지 도울 수 있다면.

EventReceivers 테이블.
ID 고유 식별자 번호 16
이름 nvarchar 아니요 512
SiteId 고유 식별자 번호 16
WebId 고유 식별자 번호 16
HostId 고유 식별자 번호 16
HostType int 번호 4
항목 아이디 int 번호 4
DirName nvarchar 번호 512
LeafName nvarchar 번호 256
유형 int 번호 4
시퀀스 번호 int 번호 4
어셈블리 nvarchar 아니오 512
클래스 nvarchar 아니오 512
데이터 nvarchar 아니오 512
필터 nvarchar 아니오 512
SourceId tContentTypeId 아니오 512
SourceType int 아니오 4
자격 증명 int 아니오 4
ContextType varbinary 아니오 16
ContextEventType varbinary no 16
ContextId varbinary no 16
ContextObjectId varbinary no 16
ContextCollectionId varbinary no 16

index_name index_description index_keys
PRIMARY SiteId에 위치한 EventReceivers_ByContextCollectionId가 클러스터되지 않음, ContextCollectionId
EventReceivers_ByContextObjectId가 PRIMARY SiteId에있는 클러스터되지 않음, ContextObjectId
EventReceivers_ById가 클러스터되지 않음, PRIMARY SiteId에 있음, Id
EventReceivers_ByTarget 클러스터에있는 유형 : ContextId, ContextType, ContextEventType, SequenceNumber, Assembly, Class
EventReceivers_IdPRIMARY ID에있는 클러스터되지 않은 고유 한 고유 키


2
무엇을해야 proc_InsertEventReceiver하고 proc_InsertContextEventReceiver우리가 XDL에서 볼 수 있습니까? 또한 병렬 처리를 줄이려면 서버 전체 설정을 사용하지 않고 이러한 명령문에 직접 영향을 미치는 이유 (MAXDOP 1 사용)는 어떻습니까?
Aaron Bertrand

1
귀하의 서버 전체 MAXDOP 설정이 무엇이며 얼마나 많은 프로세서 (논리)가 있는지 궁금합니다. SharePoint는 실제로 더 잘 작동하며 넓은 MAXDOP 서버가 1 인 서버를 선호합니다. 마음에 들지는 않지만 그것이 개발 한 방식입니다. 실제 실행 계획을 게시 할 수 있습니까? 내가 링크에서 볼 모두는 .xdl (교착 상태 그래프)입니다
마이크 월시

여러분 안녕하세요 바쁜 일정에서 시간을내어 응답 해 주셔서 감사합니다. 검토를위한 절차와 실행 계획을 모두 SkyDrive 사이트에 게시하겠습니다. 쿼리 옵션 MAXDOP (1)을 포함하도록 코드를 수정하는 것에 대해 생각했지만 그렇게하면 Microsoft에 대한 지원이 무효화됩니다. 물리적 서버는 ProLiant DL580 G4 MAXDOP 설정이 4이고 총 8 개의 물리적 프로세서가 있으며 H / T가 비활성화되어 있습니다.
SQLJarHead

안녕하세요 여러분, SkyDrive에 대한 모든 세부 정보가 포함 된 zip 패키지를 만들었습니다. 패키지의 URL을 포함하도록 원래 게시물의 본문을 수정했습니다. 문제가 무엇인지 말하지 말고 지침을 제공하고 문제를 해결하도록하십시오. 참고 : 기본 스키마에 대해 코드를 변경하거나 DDL을 수정할 수 없습니다.
SQLJarHead

1
따라서 코드를 변경할 수 없으며 스키마를 변경할 수 없습니다. 다른 솔루션은 무엇입니까? Microsoft 지원 무효화에 대해 걱정이되는 경우 Microsoft 지원이 제공된다는 것을 의미합니다. 귀하 할 수 없다는 모든 제한 사항을 감안할 때 Microsoft와 함께 지원 티켓을 여는 것을 고려 했습니까?
Aaron Bertrand

답변:


14

그것의 얼굴에, 이것은 고전적인 조회 교착 상태 처럼 보입니다 . 이 교착 상태 패턴의 필수 성분은 다음과 같습니다.

  • SELECT비 조회 비 클러스터형 인덱스를 키 조회와 함께 사용 하는 쿼리
  • INSERT클러스터형 인덱스와 비 클러스터형 인덱스를 수정 하는 쿼리

SELECT먼저 클러스터되지 않은 인덱스, 다음 클러스터 된 인덱스에 액세스합니다. INSERT액세스 클러스터 된 인덱스 첫째, 다음 클러스터되지 않은 인덱스입니다. 호환되지 않는 잠금을 획득하는 다른 순서로 동일한 자원에 액세스하는 것은 교착 상태를 '달성'할 수있는 좋은 방법입니다.

이 경우 SELECT쿼리는 다음과 같습니다.

쿼리 선택

... 그리고 INSERT쿼리는 :

INSERT 쿼리

녹색으로 강조 표시된 비 클러스터형 인덱스 유지 관리에 주목하십시오.

SELECT병렬 버전과 매우 다른 경우 계획 의 직렬 버전을 확인해야 하지만 Jonathan Kehayias가 교착 상태 처리 안내서에서 언급 한 것처럼 이 특정 교착 상태 패턴은 타이밍 및 내부 쿼리 실행 구현 세부 사항에 매우 민감합니다. 이러한 유형의 교착 상태는 종종 명백한 외부 이유없이오고갑니다.

관련 시스템에 대한 액세스 권한과 적절한 권한이 주어지면 병렬 계획에서 교착 상태가 발생하는 이유를 정확히 해결할 수 있지만 직렬은 아닙니다 (동일한 일반적인 모양으로 가정). 잠재적 인 조회 라인에는 최적화 된 중첩 루프 및 / 또는 프리 페치 점검이 포함되며, 둘 다 명령문 지속 기간 동안 분리 레벨 을 내부적으로 에스컬레이션 할 수 있습니다 REPEATABLE READ. 병렬 인덱스 탐색 범위 지정의 일부 기능이 문제에 기여할 수도 있습니다. 직렬 계획을 사용할 수있게되면 잠재적으로 흥미로워 서 세부 사항을 자세히 살펴 보는 데 시간이 걸릴 수 있습니다.

이 유형의 교착 상태에 대한 일반적인 해결책은 색인 적용을 만드는 것입니다.이 경우 열의 수는 비실용적 일 수 있습니다 (그리고 그 외에는 SharePoint에서 그러한 것들을 망쳐서는 안됩니다). 궁극적으로 SharePoint를 사용할 때 직렬 전용 계획에 대한 권장 사항은 이유가 있습니다 (물론 올바른 계획 일 필요는 없지만). 병렬 처리에 대한 비용 임계 값 의 변경 이 현재 문제를 해결하면 좋습니다. 장기적으로는 아마도 리소스 관리자를 사용하여 작업 부하를 분리하여 SharePoint 내부 쿼리가 원하는 MAXDOP 1동작을 얻고 다른 응용 프로그램이 병렬 처리를 사용할 수 있도록하려고합니다.

교착 상태 추적에 나타나는 교환 문제는 나에게 붉은 청어처럼 보입니다. 기술적으로 트리에 나타나야하는 자원을 소유하는 독립 스레드의 결과입니다. 거래소 자체가 교착 상태 문제에 직접 기여하고 있음을 시사하는 내용은 없습니다.


6

이것이 클래식 조회 교착 상태 인 경우 자원 목록에 클러스터형 인덱스 및 비 클러스터형 인덱스가 모두 포함됩니다. 일반적으로 SELECT는 NC 인덱스에서 SHARED 잠금을 유지하고 CI에서 SHARED 잠금을 기다립니다. 반면 INSERT는 CI에서 EXCLUSIVE 잠금을 획득하고 NC에서 EXCLUSIVE 잠금을 기다립니다. 이 경우 교착 상태 xml의 리소스 목록에이 두 개체가 모두 나열됩니다.

교착 상태 그래프에는 NC 색인 만 포함되므로 해당 옵션을 배제 할 수 있습니다.

또한 UNORDERED PREFETCH와의 중첩 루프 조인 으로 인해 교착 상태가 발생한 경우 실행 계획은 UNORDERED PREFETCH 알고리즘의 사용 여부를 알려줍니다 (여기서는 그렇지 않습니다) (아래 업데이트 참조).

병렬 계획으로 인해 교착 상태 라고 가정합니다 .

교착 상태 그래프가 제대로 렌더링되지 않지만 교착 상태 XML을 보면 SELECT 문 (SPID 690)의 두 스레드가 교착 상태에 포함되어 있음을 알 수 있습니다. 소비자 스레드가 1219645 페이지의 SHARED 잠금을 유지하고 port801f8ed0 (e_waitPipeGetRow)의 생산자를 기다리고 있습니다. 생산자 스레드가 1155940 페이지의 공유 잠금을 기다리고 있습니다.

INSERT 문은 1155940 페이지에서 IX 잠금을 유지하고 1219645 페이지에서 IX 잠금을 대기하여 교착 상태가 발생합니다.

SELECT 문에 대한 직렬 계획을 사용할 때 교착 상태가 두 페이지 이상에서 SHARED 잠금이 필요하지 않기 때문에 교착 상태를 피할 수 있다고 생각합니다. 또한 직렬 계획은 병렬 계획과 거의 동일하다고 생각합니다 (병렬 연산자).

[폴의 의견에 따라 업데이트]

분명히 계획은 OPTIMIZED Nested Loop 알고리즘을 사용하고 있습니다.

이는 명령문이 끝날 때까지 SHARED 잠금이 유지되는 이유를 설명합니다. 병렬 계획과 결합 된 반복 읽기는 병렬 계획이 인덱스의 다른 범위에서 잠금을 획득하고 유지할 수있는 반면, 직렬 계획은보다 순차적 인 방식으로 잠금을 획득하기 때문에 직렬 계획보다 교착 상태에 더 취약합니다.


동의했다. 이 교착 상태가 실제 LOOKUP과 관련되어 있으면 SELECT에 대한 대기 자원이 클러스터 된 인덱스를 참조했을 것입니다. DBCC PAGE를 통해 각 대기 자원 (SPID 690 대기 자원 = PAGE : 1155940 | SPID 356 대기 자원 = PAGE 1219645)의 페이지 헤더를 표시하여 둘 다 인덱스 ID 5 (IndexID 5 = EventReceivers_ByContextObjectId)를 표시하여이를 제외 할 수있었습니다. 지정된 테이블 (EventReceivers)의 NC 인덱스를 가리 킵니다.
SQLJarHead

여러분,이 흥미로운 문제를 분석하는 데 도움을 주셔서 감사합니다. 몇 가지 질문 : 1.) Roji는 병렬 SPID가 두 페이지 이상을 요청하고 있다고 지적합니다. 나는 어떤 실행 계획에서도 그것을 보지 못했습니다. INDEX SEEK 연산자의 행 수를 보면 두 생산자 중 하나의 스레드 만 행을 처리하고 있습니다. 두 페이지 이상을 요청했다는 것을 어떻게 알았습니까? (1/2)
SQLJarHead

2.) OPTIMIZED Nested Loop 알고리즘이 항상 분리 레벨을 REAPTABLE READ로 설정합니까? 실행 계획 XML 출력을 확인했으며 SPID 연결에 대해 커밋 된 읽기만 보입니다. 계획 운영자 수준에서만 호출한다고 가정합니다. (2/2)
SQLJarHead

OPTIMIZED Nested Loops의 잠금 동작은 REPEATABLE READ와 비슷 하지만 ( 이 끝날 때까지 잠금을 유지 ) 트랜잭션의 격리 수준을 REPEATABLE READ로 명시 적으로 설정하지는 않습니다. 나는 그것이 당신의 질문에도 대답한다고 생각합니다. 병렬 스레드가 한 번에 두 페이지 이상을 요청하는 것은 아니지만 한 병렬 스레드가 한 페이지에서 잠금을 보유하고 있고 다른 스레드는 다른 페이지에서 잠금을 대기 중입니다.
Roji P Thomas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.