2009-09-30 3 views
0

SQL2005에서 일부 TSQL 코드와 관련하여 이상한 문제가 있습니다. 우리가 의심 조각 문제를 생성하는동일한 레코드에서 동시 업데이트

은 다음과 같습니다

INSERT INTO SGVdProcessInfo 
    ([StartTs]) 
    VALUES 
    (GETDATE()) 

SELECT @IdProcessInfo = SCOPE_IDENTITY() 

UPDATE TOP(@quantity) 
    [SGVdTLogDetail] WITH (ROWLOCK) 
SET 
    [IdSGVdProcessInfo] = @IdProcessInfo 
WHERE 
    [IdSGVdProcessInfo] IS NULL 
    and IdTLogDetailStatus != 9 

@quantity은 일반적으로 500

소요 무슨 일이에요 클러스터되지 않은 SGVdTLogDetail

에 IdSGVdProcessInfo 및 IdTLogDetailStatus 이상 인덱스

가있다 SGVdTLogDetail의 일부 레코드가 processinfo 테이블의 하나의 id로 처음 업데이트되고 나중에 새로운 processinfo ID로 다른 프로세스에 의해 다시 업데이트된다는 것입니다. 노 걸이 힌트가이 문제를 제기하거나 아니면 다른 뭔가가 있다면 제가 궁금하네요

... 업데이트가 처음 500 선택한 행에 걸쳐 적용되는 동안

내 생각은, 다른 프로세스가 다음을 선택이다 그룹 및 아직 업데이트되지 않은 첫 번째 그룹의 일부 레코드를 가져 오는 것 (행 잠금으로 인해). 이것이 가능한가?

도움이 될 것입니다.

답변

1

예, 맞습니다. 직렬화 할 수있는 트랜잭션 내부에서 전체 작업을 수행함으로써 (동시성 손실로 인해)이를 수정할 수 있습니다. 이렇게하면 원자 수준의 읽기 및 업데이트 중에 만 트랜잭션이 실행되는 동안 모든 행이 잠기는 것을 보장 할 수 있습니다.

0

SQL Server가 행 수준의 잠금을 페이지 잠금으로 높아지고 있기 때문에 이러한 상황이 발생했다고 생각합니다. 기본 키를 지정하는 UPDATE를 사용하면 항상 행 잠금이 발생하지만 SQL Server가 이들을 포함하는 일괄 처리를 얻었을 때 그 중 일부는이 상황에 따라 같은 페이지에있을 것이라고 생각할 수 있습니다 이것은 매우 가능성이 있습니다. 예를 들어 폴더의 모든 파일을 업데이트하는 것과 거의 동시에 생성 된 파일) 페이지 잠금이 표시되고 나쁜 일이 발생합니다. UPDATE 또는 DELETE에 대한 기본 키를 지정하지 않으면 데이터베이스가 많은 영향을받지 않는다고 가정하지 않을 이유가 없으므로 페이지 잠금이 제대로 이루어지고 나쁜 결과가 발생합니다.

특히 행 수준의 잠금을 요청하면 이러한 문제는 피할 수 있지만 많은 경우 행에 영향을 미치고 데이터베이스가 주도권을 쥐고 페이지 잠금으로 확대됩니다.

관련 문제