다음을 통해 공유


Memory-Optimized 테이블의 트랜잭션

디스크 기반 테이블의 행 버전 관리(SNAPSHOT 격리 또는 READ_COMMITTED_SNAPSHOT 사용)는 낙관적 동시성 제어의 한 형태를 제공합니다. 독자와 작성자는 서로를 차단하지 않습니다. 메모리 최적화 테이블에서는 작성자가 다른 작성자를 차단하지 않습니다. 디스크 기반 테이블에서 행 버전 관리를 사용하면 하나의 트랜잭션이 행을 잠그고 행을 업데이트하려는 동시 트랜잭션이 차단됩니다. 메모리 최적화 테이블에는 잠금이 없습니다. 대신 두 트랜잭션이 동일한 행을 업데이트하려고 하면 쓰기/쓰기 충돌(오류 41302)이 발생합니다.

디스크 기반 테이블과 달리 메모리 최적화 테이블은 격리 수준이 높은 낙관적 동시성 제어, REPEATABLE READ 및 SERIALIZABLE을 허용합니다. 격리 수준을 유지하기 위해 잠금이 활용되지 않습니다. 대신 트랜잭션 유효성 검사가 끝날 때 반복 가능한 읽기 또는 직렬화 가능성 가정을 보장합니다. 가정을 위반하면 트랜잭션이 종료됩니다. 자세한 내용은 트랜잭션 격리 수준을 참조하세요.

메모리 최적화 테이블의 중요한 트랜잭션 의미 체계는 다음과 같습니다.

  • 다중 버전 관리

  • 스냅샷 기반 트랜잭션 격리

  • 낙관적인

  • 충돌 감지

이러한 각 의미 체계는 다음 섹션에서 설명합니다.

Memory-Optimized 테이블의 다중 버전 관리

메모리 최적화 테이블의 행에는 다른 버전이 있을 수 있습니다. 동시 트랜잭션은 잠재적으로 다른 버전의 동일한 행에 액세스합니다.

메모리 최적화 테이블 데이터는 버전 기반입니다. 모든 행의 경우 서로 다른 시점에 유효한 다른 행 버전이 있을 수 있습니다. 디스크 기반 테이블은 READ_COMMITTED_SNAPSHOT 또는 ALLOW_SNAPSHOT_ISOLATION ON인 경우 다른 행 버전을 유지 관리합니다. 메모리 최적화 테이블은 READ_COMMITTED_SNAPSHOT 및 ALLOW_SNAPSHOT_ISOLATION OFF인 경우에도 다른 행 버전을 유지 관리합니다. 메모리 최적화 테이블의 행 버전은 tempdb에서 유지 관리되지 않습니다. 대신 행 버전은 메모리에 행을 저장하는 메모리 최적화 데이터 구조의 일부로 인라인으로 유지됩니다.

Memory-Optimized 테이블에 대한 트랜잭션 격리 Snapshot-Based

단일 트랜잭션의 모든 작업은 메모리 최적화 테이블의 동일한 트랜잭션 일치 스냅샷을 사용합니다. 메모리 최적화 테이블에 대한 모든 트랜잭션 격리는 스냅샷 기반입니다. 예를 들어 직렬화 가능한 격리 수준을 사용하여 메모리 최적화 테이블에 액세스하는 트랜잭션은 동일한 트랜잭션 일치 스냅샷에서 모든 작업을 수행합니다.

메모리 최적화 테이블에 액세스하는 트랜잭션은 이 행 버전 관리 작업을 사용하여 테이블의 행에 대한 트랜잭션 일치 스냅샷을 가져옵니다. 트랜잭션 내 모든 문에서 읽은 데이터는 트랜잭션이 시작될 때 존재했던 데이터의 트랜잭션 일관성을 가진 버전입니다. 따라서 동시에 실행되는 트랜잭션이 수정한 내용은 현재 트랜잭션 내의 문장 또는 쿼리에 표시되지 않습니다.

Memory-Optimized 테이블에 대한 낙관적 동시성 제어

충돌 및 오류는 드물며 메모리 최적화 테이블의 트랜잭션은 동시 트랜잭션과 충돌하지 않고 작업이 성공했다고 가정합니다. 트랜잭션은 트랜잭션 격리를 보장하기 위해 메모리 최적화 테이블에서 잠금 또는 래치를 사용하지 않습니다. 작가들은 독자들을 차단하지 않습니다. 작가는 다른 작가를 방해하지 않습니다. 대신 트랜잭션은 다른 트랜잭션과 충돌하지 않을 것이라는 (낙관적) 가정 하에 진행됩니다. 잠금 및 래치를 사용하지 않고 다른 트랜잭션이 동일한 행 처리를 완료할 때까지 기다리지 않으면 성능이 향상됩니다.

또한 트랜잭션(TxA)이 커밋하는 프로세스에 있는 다른 트랜잭션(TxB)에 의해 삽입되거나 수정된 행을 읽는 경우 커밋이 발생할 때까지 기다리지 않고 다른 트랜잭션이 커밋된다고 낙관적으로 가정합니다. 이 경우 트랜잭션 TxA는 트랜잭션 TxB에 대한 커밋 종속성을 취합니다.

충돌 검색, 유효성 검사 및 커밋 종속성 검사

SQL Server는 동시 트랜잭션 간의 충돌과 격리 수준 위반을 검색하고 충돌하는 트랜잭션 중 하나를 종료합니다. 이 트랜잭션을 다시 시도해야 합니다. (자세한 내용은 Memory-Optimized 테이블의 트랜잭션에 대한 재시도 논리에 대한 지침을 참조하세요.)

시스템은 충돌이 없고 트랜잭션 격리 위반이 없다고 낙관적으로 가정합니다. 데이터베이스의 불일치를 유발하거나 트랜잭션 격리를 위반할 수 있는 충돌이 발생하면 이러한 충돌이 감지되고 트랜잭션이 종료됩니다.

충돌이 감지되면 트랜잭션이 종료되고 클라이언트가 다시 시도해야 합니다.

다음 표에는 메모리 최적화 테이블에 액세스하는 트랜잭션의 오류 조건이 요약되어 있습니다.

메모리 최적화 테이블에 액세스하는 트랜잭션에 대한 오류 조건입니다.

오류 시나리오
데이터 쓰기 충돌. 트랜잭션이 시작된 이후 업데이트된 레코드를 업데이트하려고 합니다. 동시 트랜잭션에 의해 업데이트되거나 삭제된 행을 업데이트하거나 삭제합니다.
반복 가능한 읽기 유효성 검사 실패입니다. 트랜잭션이 읽은 행이 트랜잭션이 시작된 이후 변경(업데이트 또는 삭제)되었습니다. 반복 가능한 읽기 유효성 검사는 일반적으로 REPEATABLE READ 및 SERIALIZABLE 트랜잭션 격리 수준을 사용할 때 발생합니다.
직렬화 가능한 유효성 검사 실패입니다. 거래가 시작된 이후, 검색 범위 중 하나에 새로운 (가상) 행이 삽입되었습니다. 트랜잭션이 시작되기 전에 행이 데이터베이스에 커밋된 경우 행이 트랜잭션에 표시되었을 것입니다. SERIALIZABLE 유효성 검사는 일반적으로 SERIALIZABLE 격리를 사용하고 PRIMARY KEY 제약 조건의 유효성을 검사할 때 발생합니다.
종속성 오류를 커밋합니다. 트랜잭션은 이 테이블의 오류 중 하나, 메모리 부족 상태 또는 트랜잭션 로그에 커밋 실패로 인해 커밋에 실패한 다른 트랜잭션에 종속되었습니다. 이 오류는 읽기/쓰기 및 읽기 전용 트랜잭션 모두에서 발생할 수 있습니다.

트랜잭션 기간

이전 테이블에 언급된 오류는 트랜잭션 중에 다른 지점에서 발생할 수 있습니다. 다음 그림에서는 메모리 최적화 테이블에 액세스하는 트랜잭션의 단계를 보여 줍니다.

트랜잭션의 수명입니다. 메모리 최적화 테이블에 액세스하는 트랜잭션의 수명입니다.

일반 처리

이 단계에서는 사용자가 작성한 Transact-SQL 문장이 실행됩니다. 행은 테이블에서 읽혀지고 새 행 버전은 데이터베이스에 기록됩니다. 트랜잭션은 다른 모든 동시 트랜잭션에서 격리됩니다. 트랜잭션은 트랜잭션 시작 시 존재하는 메모리 최적화 테이블의 스냅샷을 사용합니다.

이 트랜잭션 단계의 테이블에 대한 쓰기는 아직 다른 트랜잭션에 표시되지 않습니다. 한 가지 예외: 행 업데이트 및 삭제는 쓰기 충돌을 감지하기 위해 다른 트랜잭션에서 작업을 업데이트하고 삭제하는 데 표시됩니다.

업데이트 또는 삭제 작업에서 트랜잭션의 논리적 시작 이후 행이 업데이트되거나 삭제된 것으로 확인되면 오류 41302로 인해 작업이 실패합니다. 오류 41302에 대한 메시지는 "현재 트랜잭션이 이 트랜잭션이 시작된 이후 업데이트된 X 테이블의 레코드를 업데이트하려고 했습니다. 트랜잭션이 중단되었습니다."

이 오류는 트랜잭션을 종료합니다(XACT_ABORT OFF인 경우에도). 즉, 사용자 세션이 종료될 때 트랜잭션이 롤백됩니다. 종료된 트랜잭션은 커밋할 수 없으며 로그에 쓰지 않고 메모리 최적화 테이블에 액세스하지 않는 읽기 작업만 지원합니다.

종속성 커밋

정기적으로 처리하는 동안 트랜잭션은 유효성 검사 또는 커밋 단계에 있지만 아직 커밋되지 않은 다른 트랜잭션에서 작성한 행을 읽을 수 있습니다. 트랜잭션의 논리적 종료 시간이 유효성 검사 단계의 시작 부분에 할당되었기 때문에 행이 표시됩니다.

트랜잭션이 커밋되지 않은 행을 읽는 경우 해당 트랜잭션에 대한 커밋 종속성을 사용합니다. 여기에는 두 가지 주요 의미가 있습니다.

  • 트랜잭션이 의존하는 다른 트랜잭션이 커밋될 때까지 해당 트랜잭션은 커밋될 수 없습니다. 즉, 모든 종속성이 지워질 때까지 커밋 단계를 입력할 수 없습니다.

  • 또한 모든 종속성이 지워질 때까지 결과 집합이 클라이언트에 반환되지 않습니다. 이렇게 하면 클라이언트가 커밋되지 않은 데이터를 관찰할 수 없습니다.

종속 트랜잭션이 커밋에 실패하면 커밋 종속성 오류가 발생합니다. 즉, 트랜잭션이 오류 41301로 커밋되지 않음을 의미합니다("현재 트랜잭션이 종속성을 취한 이전 트랜잭션이 중단되었으며 현재 트랜잭션은 더 이상 커밋할 수 없습니다.").

유효성 검사 단계

유효성 검사 단계에서 시스템은 요청된 트랜잭션 격리 수준에 필요한 가정이 트랜잭션의 논리적 시작과 논리적 끝 사이에 참인지 확인합니다.

유효성 검사 단계가 시작될 때 트랜잭션에 논리적 종료 시간이 할당됩니다. 데이터베이스에 기록된 행 버전은 논리적 종료 시간에 다른 트랜잭션에 표시됩니다. 자세한 내용은 커밋 종속성을 참조하세요.

반복 가능한 읽기 유효성 검사

트랜잭션의 격리 수준이 REPEATABLE READ 또는 SERIALIZABLE이거나 REPEATABLE READ 또는 SERIALIZABLE 격리에서 테이블에 액세스하는 경우(자세한 내용은 트랜잭션 격리 수준에서 개별 작업의 격리 섹션 참조) 시스템은 읽기가 반복 가능한지 확인합니다. 즉, 트랜잭션에서 읽은 행의 버전이 트랜잭션의 논리적 종료 시간에 유효한 행 버전인지 확인합니다.

행이 업데이트되거나 변경된 경우 트랜잭션이 오류 41305("반복 가능한 읽기 유효성 검사 실패로 인해 현재 트랜잭션을 커밋하지 못했습니다.")로 커밋하지 못합니다.

이 오류는 삽입, 업데이트 또는 삭제 작업 후 및 트랜잭션이 커밋되기 전에 테이블을 삭제하는 경우에도 발생할 수 있습니다. 고유하게 컴파일된 저장 프로시저의 삽입, 업데이트 또는 삭제 작업에만 적용됩니다. 해석된 Transact-SQL 통해 수행되는 이러한 쓰기 작업으로 인해 DROP TABLE 문이 차단되고 트랜잭션이 커밋될 때까지 기다립니다.

직렬화 가능 유효성 검사

직렬화 가능 유효성 검사는 다음 두 가지 경우에 수행됩니다.

  • 트랜잭션의 격리 수준이 SERIALIZABLE이거나 SERIALIZABLE 격리 수준에서 테이블에 액세스하는 경우.

  • 행이 고유 인덱스에 삽입되는 경우(예: PRIMARY KEY 제약 조건에 대해 생성된 인덱스) 시스템은 동일한 키를 가진 행이 동시에 삽입되지 않은지 확인합니다.

시스템에서는 가상 행이 데이터베이스에 기록되지 않은지 확인합니다. 트랜잭션에서 수행하는 읽기 작업은 이러한 읽기 작업의 검색 범위에 새 행이 삽입되지 않은지 확인하기 위해 평가됩니다.

고유 인덱스의 키 삽입에는 키가 중복되지 않는지 확인하기 위한 암시적 읽기 작업이 포함됩니다. 고유 인덱스에 대한 직렬화 가능한 유효성 검사를 수행하면 두 트랜잭션이 동시에 동일한 키를 삽입하는 경우 이러한 인덱스에 중복이 있을 수 없습니다.

가상 행이 검색되면 트랜잭션이 오류 41325("직렬화 가능한 유효성 검사 실패로 인해 현재 트랜잭션을 커밋하지 못했습니다.")로 커밋하지 못합니다.

커밋 처리

유효성 검사가 성공하고 모든 트랜잭션 종속성이 지워지면 트랜잭션이 커밋 처리 단계로 들어갑니다. 이 단계에서 지속성 테이블의 변경 내용은 로그에 기록되고 로그는 내구성을 보장하기 위해 디스크에 기록됩니다. 트랜잭션의 로그 레코드가 디스크에 기록되면 컨트롤이 클라이언트에 반환됩니다.

이 트랜잭션에 대한 모든 커밋 종속성이 지워지고 이 트랜잭션이 커밋되기를 기다리던 모든 트랜잭션이 계속 진행될 수 있습니다.

제한점

  • 데이터베이스 간 트랜잭션은 메모리 최적화 테이블에서 지원되지 않습니다. 메모리 최적화 테이블에 액세스하는 모든 트랜잭션은 tempdb에 대한 읽기-쓰기 액세스 및 시스템 데이터베이스 마스터에 대한 읽기 전용 액세스를 제외하고 둘 이상의 데이터베이스에 액세스할 수 없습니다.

  • 분산 트랜잭션은 메모리 최적화 테이블에서 지원되지 않습니다. BEGIN DISTRIBUTED TRANSACTION으로 시작된 분산 트랜잭션은 메모리 최적화 테이블에 액세스할 수 없습니다.

  • 메모리 최적화 테이블은 잠금을 지원하지 않습니다. 잠금 힌트(예: TABLOCK, XLOCK, ROWLOCK)를 통한 명시적 잠금은 메모리 최적화 테이블에서 지원되지 않습니다.

또한 참조하십시오

Memory-Optimized 테이블의 트랜잭션 이해