2013-09-05 4 views
4

웹 사이트에 매우 인기있는 포럼이 있으며 가끔씩 같은 포럼에서 동일한 두 개의 (데이터 내 빼기) 업데이트 문 사이에 여러 가지 교착 상태가 발생하는 경우가 있습니다. 이 쿼리에는 왜 이런 문제가 발생하는지 정확히 알지 못합니다. 문제없이 높은 동시성으로 실행되는 사이트의 다른 많은 쿼리가 있기 때문입니다.두 개의 업데이트 문 사이에 SQL Server 교착 상태가 있습니다.

update [Forum] set [DateModified] = @DateModified, [LatestLocalThreadID] = @LatestLocalThreadID where ID = 310  

사람이 원인이 될 수 있는지에 어떤 도움이 되거 수 : 두 프로세스 사이의

Update Deadlock Graph

Full Image

쿼리는 그래프로 보여줍니다 거의 동일하다?

답변

2

LatestLocalThreadID을 설정하면 문이 완료 될 때 행이 계속 있는지 확인하기 위해 S 잠금을 생성하는 ForumThreads에 대한 외래 키가 있기 때문입니다. 가능한 수정 프로그램은 업데이트 문 앞에

SELECT * 
FROM ForumThreads WITH (XLOCK, ROWLOCK, HOLDLOCK) 
WHERE ID = @LatestLocalThreadID 

과 X- 잠금을 추가하는 것입니다. 덜 공격적인 모드로 UPDLOCK을 시도 할 수도 있습니다. 물론 다른 곳에서는 교착 상태가 발생할 수 있지만 가장 좋은 첫 번째 시도입니다.

1

기본적으로 교착 상태는 동일한 순서로 개체 (테이블, 페이지, 행)에 항상 액세스함으로써 방지됩니다. 귀하의 예제에서는 하나의 프로세스가 forum을 먼저 액세스하고 forumThread 초를 액세스하고 다른 스레드는 그 반대의 작업을 수행합니다. update은 일반적으로 먼저 업데이트 할 행을 검색하고 검색 중에 S- 잠금을 사용합니다. 변경된 것으로 식별 된 행은 X 잠금에 의해 잠겨져 실제 변경이 발생합니다.

신속하고 더러운 해결책은 begin Tran 다음에 필요한 객체 순서대로 lock을 수행하고 업데이트를 수행 한 다음 잠금을 다시 해제 할 commit을 입력하면됩니다. 그러나 이것은 자물쇠를 막기 때문에 당신의 웹 사이트의 전반적인 침체를 가져올 것입니다.

더 좋은 방법은 두 개의 문장을 식별하는 것입니다 (질문을 편집하고 발견했을 때 다른 것을 제공 할 수 있음). 그리고 그것의 실행 계획. 트랜잭션을 다시 작성하여 동일한 순서로 모든 객체에 액세스하고 교착 상태를 방지 할 수 있어야합니다.