2016-11-14 7 views
2

여러 행을 하나로 결합하는 SQL Server 2014 데이터베이스에 연결된 응용 프로그램이 있습니다. 응용 프로그램이 실행 중일 때이 데이터베이스에는 다른 연결이 없습니다.SQL Server의 교착 상태 방지

먼저 특정 시간 범위 내의 행을 선택하십시오. 이 쿼리는 클러스터 된 조회와 병합 된 클러스터되지 않은 검색 (TIME 열)을 사용합니다.

select ... 
from FOO 
where TIME >= @from and TIME < @to and ... 

다음, 우리는 C#에서 이러한 행을 처리하고 하나의 갱신 및 다중 삭제 등의 변경을 쓰기,이 덩어리마다 여러 번 발생합니다. 또한 클러스터되지 않은 인덱스 검색을 사용합니다.

begin tran 

update FOO set ... 
where NON_CLUSTERED_ID = @id 

delete FOO where NON_CLUSTERED_ID in (@id1, @id2, @id3, ...) 

commit 

여러 병렬 덩어리로 이것을 실행할 때 교착 상태가 발생합니다. 나는 updatedelete에 대해 ROWLOCK을 사용해 보았습니다.하지만 청크 사이에 겹침이 없더라도 어떤 이유로 든 이전보다 훨씬 많은 교착 상태가 발생했습니다.

update에서 TABLOCKX, HOLDLOCK을 시도했지만 병렬 처리의 이점을 잃어 버리므로 내 select을 병렬로 수행 할 수 없음을 의미합니다.

어떻게하면 교착 상태를 피할 수 있지만 여러 개의 병렬 청크를 처리 할 수 ​​있습니까?

selectNOLOCK을 사용하는 것이 안전할까요? 청크 사이에 행이 중복되지 않는다면이 경우 어떻게해야합니까? 그런 다음 TABLOCKX, HOLDLOCKupdatedelete만을 차단합니까?

아니면 그냥 교착 상태가 발생하여 응용 프로그램에서 쿼리를 다시 시도해도된다는 것을 받아 들여야합니까?

UPDATE (추가 정보) : 모든 교착 상태가 지금까지 updatedelete 단계에서 일어난는 select 없음. 오늘 해결할 수 없다면 교착 상태 로그를 얻으려고 노력할 것입니다 (올바른 추적 플래그는 이전에 활성화되지 않았습니다).

UPDATE :이 ROWLOCK 발생하는 교착 상태의이 개 배치되어, 그들은 모두 만 delete 문과가 사용하는 클러스터되지 않은 인덱스를 참조하십시오. 테이블의 힌트없이 발생하는 교착 상태와 동일한 것인지 확실하지 않습니다. 이러한 힌트 중 일부는 재현 할 수 없었습니다. Deadlock 2

그렇지 않으면 .xdl에서 필요한 것도이 있는지 물어

Deadlock 1

, 나는 전체를 부착 조금 피곤 해요.

+0

선택 중에 'UPDLOCK'을 (를) 주장 했습니까? 이렇게하면 교착 상태에서 벗어나도록 업데이트/삭제할 때 잠금이 이미 있습니다. 가능한 경우 교착 상태 로깅 세부 정보를 공유하십시오. – Jens

+1

모든 처리를 저장 프로 시저로 옮길 수 있습니까? 또한 스냅 샷 격리를 켜기 만하면 해결할 수 있지만 실제로 수행중인 작업에 따라 다릅니다. –

+0

@Jens 불행히도 지금 당장 교착 상태 로그를 가져올 수 없습니다. 교착 상태로 인해 실패한 모든 스레드가'update' 및'delete' 단계에있는 것으로 보이므로'select' 잠금을 변경하면이 경우에 영향을 미치지 않습니다. 교착 상태 로그를 얻지 못했습니다. 다음 시도를 위해 교착 상태 추적 플래그를 사용할 수 있는지 확인할 것입니다. @ Nick.McDermaid 불행히도 스냅 샷 격리를 사용할 수 없습니다. –

답변

0

교착 상태와 관련된 일반적인 조언 : 동일한 순서로 모든 작업을 수행해야합니다. 즉, 서로 다른 프로세스에 대해 동일한 순서로 잠금을 획득해야합니다.

Minimizing Deadlocks과 관련된 microsoft.com의 기술 문서에서도 동일한 조언을 찾을 수 있습니다. 먼저 열거 된 이유가 있습니다. 같은 순서로

  • Access 개체.
  • 트랜잭션에서 사용자 상호 작용을 피하십시오.
  • 트랜잭션을 짧고 한 번에 처리하십시오.
  • 낮은 격리 수준을 사용하십시오.
  • 행 버전 관리 기반 격리 수준을 사용하십시오.
  • 읽기 커밋 된 트랜잭션이 행 버전 관리를 사용하려면 READ_COMMITTED_SNAPSHOT 데이터베이스 옵션을 ON으로 설정하십시오.
  • 스냅 샷 격리를 사용하십시오.
  • 바운드 연결을 사용하십시오.

업데이트 카토에서 질문 후 : 같은 순서로

어떻게 획득 할 잠금은 여기에 적용? 그가 SQL을 어떻게 바꿀 것인지에 대한 조언이 있습니까?

교착 상태에 상관없이 항상 동일하지 어떤 환경 : 다른 순서로 두 프로세스 (예를 들어 A & B) 다수의 잠금을 획득 (X & Y 말) A가 기다리고 YB을 기다리고 있도록 X 인 반면 AX이고, BY을 보유하고 있습니다.

DELETEUPDATE 문은 암시 적으로 행이나 인덱스 범위 또는 테이블 (엔진이 적절하다고 판단하는 내용에 따라 다름)에서 잠금을 획득하기 때문에 적용됩니다.

프로세스를 분석하고 잠금을 다른 순서로 얻을 수있는 시나리오가 있는지 확인해야합니다. 그래도 아무 것도 표시되지 않으면 analyze deadlocks using the SQL Server Profiler :

추적 할 수 있습니다. 교착 상태 이벤트를 추적하려면 데드락 그래프 이벤트 클래스를 추적에 추가하십시오. 이 이벤트 클래스는 프로세스의 XML 데이터 및 교착 상태와 관련된 개체로 추적의 TextData 데이터 열을 채 웁니다. SQL Server Profiler는 XML 문서를 나중에 SQL Server Management Studio에서 볼 수있는 교착 상태 XML (.xdl) 파일로 추출 할 수 있습니다. 교착 상태 그래프 이벤트를 모든 교착 상태 그래프 이벤트가 포함 된 단일 파일로 추출하거나 파일을 분리하도록 SQL Server 프로파일 러를 구성 할 수 있습니다.

+0

동일한 순서로 잠금을 획득하는 것이 여기에 어떻게 적용됩니까? 그가 SQL을 어떻게 바꿀 것인지에 대한 조언이 있습니까? – Cato

+0

@Cato 업데이트 된 답변에 주어진 추가 상황. –

+0

질문에 교착 상태 그래프를 추가했습니다. 둘 다'delete' 문을 참조하는 것 같습니다. –

0

이 코드의 여러 인스턴스가 병렬로 실행되는 것을 방지하기 위해 업데이트 트랜잭션에 sp_getapplock을 사용하고 싶습니다. 테이블 잠금 힌트처럼 선택 문을 차단하지 않습니다.

잠금을 획득하는 데 시간이 오래 걸릴 수 있기 때문에 다시 시도 논리를 프로그래밍해야합니다.

업데이트 트랜잭션을 sp_getapplock으로 래핑하는 방법입니다.

BEGIN TRANSACTION; 
BEGIN TRY 

    DECLARE @VarLockResult int; 
    EXEC @VarLockResult = sp_getapplock 
     @Resource = 'some_unique_name_app_lock', 
     @LockMode = 'Exclusive', 
     @LockOwner = 'Transaction', 
     @LockTimeout = 60000, 
     @DbPrincipal = 'public'; 

    IF @VarLockResult >= 0 
    BEGIN 
     -- Acquired the lock 
     update FOO set ... 
     where NON_CLUSTERED_ID = @id 

     delete FOO where NON_CLUSTERED_ID in (@id1, @id2, @id3, ...) 

    END ELSE BEGIN 
     -- return some error code, so that the caller could retry 
    END; 

    COMMIT TRANSACTION; 
END TRY 
BEGIN CATCH 
    ROLLBACK TRANSACTION; 
    -- handle the error 
END CATCH; 

선택 진술 문은 변경할 필요가 없습니다.

덩어리로 된 ID가 겹치지 않는다고해도 나는 NOLOCK을 추천합니다. 이 힌트를 사용하면 SELECT 쿼리가 변경되는 일부 페이지를 건너 뛸 수 있으므로 일부 페이지를 두 번 읽을 수 있습니다. 그러한 행동이 용인 될 것 같지는 않습니다.

+0

'sp_getapplock'이 현재 구현보다 느리고 모든 교착 상태를 다시 시도하는 것이 좋습니다. 'NOLOCK'에 대한 정보를 보내 주셔서 감사합니다. –