TL : DR : 아래 질문은 다음과 같이 요약됩니다. 행을 삽입 할 때 새 값 생성Identity
과 클러스터 된 인덱스에서 해당 행 키 잠금 사이에 기회 창이 있습니까? 외부 관찰자가 더 새로운 것을 볼 수 있습니다. Identity
동시 거래에 의해 삽입 된 가치? (SQL Server에서)
상세 버전
테이블의 클러스터형 인덱스 (여러 개의 추가 비 클러스터형 인덱스도 있음)의 키인 Identity
이라는 열 이있는 SQL Server 테이블 CheckpointSequence
이 있습니다. 여러 개의 동시 프로세스 및 스레드에 의해 행이 테이블에 삽입 됩니다 (분리 레벨 READ COMMITTED
에서 및 제외 IDENTITY_INSERT
). 동시에, 클러스터형 인덱스에서 행을 주기적으로 읽는 프로세스가 있습니다 CheckpointSequence
( 옵션이 해제 된 상태 에서 격리 레벨 READ COMMITTED
에 READ COMMITTED SNAPSHOT
있음).
저는 현재 읽기 프로세스가 체크 포인트를 "건너 뛰지"못한다는 사실에 의존하고 있습니다. 내 질문은 : 이 부동산에 의존 할 수 있습니까? 그렇지 않다면, 그것을 실현시키기 위해 어떻게해야합니까?
예 : ID 값이 1, 2, 3, 4 및 5 인 행을 삽입하는 경우 독자 는 값이 4 인 행을보기 전에 값이 5 인 행을 볼 수 없어야합니다 . 테스트는 ORDER BY CheckpointSequence
절이 포함 된 쿼리 ( 그리고 WHERE CheckpointSequence > -1
절), 4 행이있을 때마다 안정적으로 블록은 5 행이 이미 커밋 된 경우에도 읽을 수 있지만 아직 커밋하지합니다.
나는 적어도 이론 상으로는이 가정이 깨질 수있는 경쟁 조건이있을 수 있다고 생각합니다. 불행히도, on on documentation 은 여러 동시 트랜잭션의 컨텍스트에서 작동 Identity
하는 Identity
방식에 대해 많이 말하지 않으며 "현재 시드 및 증분을 기반으로 새로운 각 값이 생성됩니다"라고 말합니다. "특정 거래에 대한 각각의 새로운 가치는 테이블에있는 다른 동시 거래와 다릅니다." ( MSDN )
내 추론은 다음과 같이 작동해야합니다.
- 트랜잭션이 명시 적 또는 암시 적으로 시작됩니다.
- ID 값 (X)이 생성됩니다.
- 해당 행 잠금은 ID 값을 기반으로 클러스터형 인덱스에서 가져옵니다 (잠금 에스컬레이션이 시작되지 않는 경우 전체 테이블이 잠김).
- 행이 삽입됩니다.
- 트랜잭션이 커밋되어 (아마도 시간이 많이 걸릴 수 있음) 잠금이 다시 제거됩니다.
2 단계와 3 단계 사이에는 아주 작은 창이 있으며
- 동시 세션은 다음 ID 값 (X + 1)을 생성하고 나머지 모든 단계를 실행할 수 있습니다.
- 따라서 해당 시점에 정확하게 오는 리더가 X + 1 값을 읽을 수있게하여 X 값이 누락됩니다.
물론,이 확률은 매우 낮습니다. 그러나 여전히-일어날 수 있습니다. 아니면 할 수 있습니까?
컨텍스트에 관심이있는 경우 NEventStore의 SQL Persistence Engine 구현입니다. NEventStore는 모든 이벤트가 새로운 오름차순 체크 포인트 시퀀스 번호를 얻는 추가 전용 이벤트 저장소를 구현합니다. 클라이언트는 체크 포인트별로 정렬 된 이벤트 저장소에서 이벤트를 읽습니다. 검사 점이 X 인 이벤트가 처리되면 클라이언트는 "최신"이벤트, 즉 검사 점이 X + 1 이상인 이벤트 만 고려하므로 이벤트를 건너 뛸 수없는 것이 중요합니다. . 그들이 다시 고려하지 않을 거라고 나는 현재 여부를 결정하기 위해 노력하고있어 Identity
. 기반의 체크 포인트의 구현이 요구 사항을 충족 이들은되어 사용되는 정확한 SQL 문 : 스키마 , 작가의 쿼리는 ,독자의 질문 .)
내가 옳고 위에서 설명한 상황이 발생할 수 있다면, 두 가지 옵션 중 두 가지만 만족할 수 있습니다.
- X를보기 전에 체크 포인트 시퀀스 값 X + 1을 볼 때 X + 1을 닫고 나중에 다시 시도하십시오. 그러나
Identity
물론 갭을 생성 할 수 있기 때문에 (예 : 트랜잭션이 롤백 될 때) X는 절대로 오지 않을 수 있습니다. - 따라서 동일한 접근 방식이지만 n 밀리 초 후에 간격을 허용하십시오. 그러나 어떤 n 값을 가정해야합니까?
더 좋은 아이디어가 있습니까?