메모리 액세스에 최적화된 테이블의 트랜잭션
디스크 기반 테이블의 행 버전 관리(SNAPSHOT 격리 또는 READ_COMMITTED_SNAPSHOT 사용)는 낙관적 동시성 제어의 형태를 사용합니다. 판독기와 기록기는 서로를 차단하지 않습니다. 메모리 최적화 테이블을 사용하면 기록기는 기록기를 차단하지 않습니다. 디스크 기반 테이블에서 행 버전 관리를 사용하면 한 트랜잭션은 행을 잠그며 이 행을 업데이트하려고 하는 동시 트랜잭션은 차단됩니다. 메모리 최적화 테이블을 사용할 때는 잠금 기능이 없습니다. 대신 두 트랜잭션이 같은 행을 업데이트하려고 하는 경우 쓰기/쓰기 충돌이 발생하게 됩니다(오류 41302).
디스크 기반 테이블과 달리 메모리 최적화 테이블을 사용하면 더 높은 격리 수준인 REPEATABLE READ 및 SERIALIZABLE을 사용하여 낙관적 동시성 제어를 할 수 있습니다. 격리 수준을 적용하기 위해 잠금은 수행되지 않습니다. 대신 트랜잭션이 끝나면 반복 읽기나 순차성 가정을 확실하기 하기 위해 유효성 검사가 수행됩니다. 가정을 위반하는 경우 트랜잭션이 종료됩니다. 자세한 내용은 Transaction Isolation Levels을 참조하세요.
메모리 최적화 테이블의 중요한 트랜잭션 의미는
다중 버전 관리
스냅샷 기반 트랜잭션 격리
Optimistic
충돌 검색
각각에 대한 의미는 다음 섹션에서 설명합니다.
메모리 액세스에 최적화된 테이블에서 다중 버전 관리
메모리 최적화 테이블의 행에 다른 버전이 있을 수 있습니다. 동시 트랜잭션은 같은 행의 다른 버전에 액세스할 가능성이 있습니다.
메모리 액세스에 최적화된 테이블은 버전을 기반으로 합니다. 모든 행에 대해 다른 행 버전이 있을 수 있으며 다른 시점에서 유효합니다. READ_COMMITTED_SNAPSHOT 또는 ALLOW_SNAPSHOT_ISOLATION이 ON이면 디스크 기반 테이블에서 여러 행 버전을 유지합니다. 메모리 액세스에 최적화된 테이블은 READ_COMMITTED_SNAPSHOT 및 ALLOW_SNAPSHOT_ISOLATION이 OFF여도 다른 행 버전을 유지합니다. tempdb에서는 메모리 최적화 테이블의 행 버전이 유지되지 않습니다. 대신, 행 버전은 메모리에 행을 저장하는 메모리 최적화 데이터 구조의 한 부분으로 인라인으로 유지됩니다.
메모리 액세스에 최적화된 테이블의 스냅샷 기반 트랜잭션 격리
단일 트랜잭션의 모든 작업은 트랜잭션 측면에서 메모리 최적화 테이블의 동일한 일관성 스냅샷을 사용합니다. 메모리 최적화 테이블의 모든 트랜잭션 격리는 스냅샷을 기반으로 합니다. 예를 들어, 직렬화 가능 격리 수준을 사용하여 메모리 최적화 테이블에 액세스하는 트랜잭션은 동일한 트랜잭션 측면에서 일관된 스냅샷에서 모든 작업을 수행합니다.
메모리 최적화 테이블에 액세스하는 트랜잭션은 이 행 버전 관리를 사용하여 트랜잭션 측면에서 테이블에 있는 행의 일관된 스냅샷을 얻습니다. 트랜잭션의 문이 읽은 데이터는 트랜잭션을 시작할 때 존재하던 데이터 버전과 트랜잭션별로 일관성이 유지됩니다. 따라서 동시에 실행 중인 트랜잭션의 수정 내용이 현재 트랜잭션의 문에는 표시되지 않습니다.
메모리 액세스에 최적화된 테이블의 낙관적 동시성 제어
충돌과 오류는 드물게 발생하며 메모리 최적화 테이블의 트랜잭션은 동시 트랜잭션과의 충돌이 없고 작업이 성공한다고 가정합니다. 트랜잭션에서 트랜잭션 격리를 보증하기 위해 메모리 최적화 테이블에 잠금이나 래치를 사용하지 않습니다. 기록기는 판독기를 차단하지 않습니다. 기록기는 기록기를 차단하지 않습니다. 대신 트랜잭션은 다른 트랜잭션과 충돌이 없을 것이라는 (낙관적) 가정 하에서 처리됩니다. 잠금과 래치를 사용하지 않고 다른 트랜잭션에서 같은 행 처리를 마칠 때까지 기다리지 않으면 성능이 향상됩니다.
또한 커밋 중인 다른 트랜잭션(TxB)이 삽입하거나 수정한 행을 트랜잭션(TxA)이 읽는 경우 커밋이 발생하기를 기다리는 대신 다른 트랜잭션이 커밋한다고 낙관적으로 가정합니다. 이 경우 트랜잭션 TxA는 트랜잭션 TxB에서 커밋 종속성을 수행합니다.
충돌 검색, 유효성 검사 및 커밋 종속성 확인
SQL Server 동시 트랜잭션 간의 충돌과 격리 수준 위반을 검색하고 충돌하는 트랜잭션 중 하나를 종료합니다. 이 트랜잭션은 다시 시도해야 합니다. 자세한 내용은 Memory-Optimized 테이블의 트랜잭션에 대한 재시도 논리에 대한 지침을 참조하세요.
시스템은 아무 충돌도 없고 트랜잭션 격리의 위반이 없다고 낙관적으로 가정합니다. 충돌이 있어 데이터베이스에 불일치가 발생하거나 트랜잭션 격리를 위반할 수 있는 경우 이러한 충돌은 감지되고 트랜잭션이 종료됩니다.
충돌이 감지되면 트랜잭션이 종료되고 클라이언트를 다시 시도해야 합니다.
다음 표에는 메모리 최적화 테이블에 액세스하는 트랜잭션에 대한 오류 조건이 요약되어 있습니다.
메모리 최적화 테이블에 액세스하는 트랜잭션에 대한 오류 조건.
오류 | 시나리오 |
---|---|
쓰기 충돌. 트랜잭션이 시작된 이후 업데이트된 레코드를 업데이트 하려고 시도. | 동시 트랜잭션에 의해 업데이트 또는 삭제된 행을 업데이트하거나 삭제합니다. |
반복 가능한 읽기 유효성 검사 오류. | 트랜잭션이 시작된 이후 트랜잭션에서 읽은 행이 변경되었습니다(업데이트 또는 삭제). 반복 읽기 유효성 검사는 대개 REPEATABLE READ 및 SERIALIZABLE 트랜잭션 격리 수준을 사용할 때 발생합니다. |
직렬화 유효성 검사 오류. | 트랜잭션이 시작된 이후 새로운(가상) 행이 트랜잭션의 검색 범위 중 하나에 삽입되었습니다. 트랜잭션이 시작되기 전에 행이 데이터베이스에 커밋된 경우 트랜잭션에 해당 행이 표시됩니다. SERIALIZABLE 유효성 검사는 대개 SERIALIZABLE 격리를 사용하고 PRIMARY KEY 제약 조건의 유효성을 검사할 때 발생합니다. |
커밋 종속성이 실패했습니다. | 트랜잭션이 이 테이블의 오류 중 하나, 메모리 부족 상태 또는 트랜잭션 로그에 대한 커밋 실패로 인해 커밋하지 못한 다른 트랜잭션에서 종속성을 수행했습니다. 이 오류는 읽기/쓰기와 읽기 전용 트랜잭션에서 발생할 수 있습니다. |
트랜잭션 수명
이전 테이블에서 언급한 오류는 트랜잭션 중 여러 지점에서 발생할 수 있습니다. 다음 그림은 메모리 최적화 테이블에 액세스하는 트랜잭션의 단계를 보여줍니다.
메모리 최적화 테이블에 액세스하는 트랜잭션의 수명입니다.
일반 처리
이 단계에서는 사용자가 발급한 Transact-SQL 문이 실행됩니다. 테이블에서 행을 읽고 데이터베이스에 새로운 행 버전을 기록합니다. 트랜잭션은 다른 모든 동시 트랜잭션으로부터 격리됩니다. 트랜잭션은 트랜잭션 시작 시 있는 메모리 최적화 테이블의 스냅샷을 사용합니다.
이 트랜잭션 단계의 테이블에 대한 쓰기는 아직 다른 트랜잭션에 표시되지 않습니다. 단, 행 업데이트 및 삭제는 쓰기 충돌을 감지하기 위해 다른 트랜잭션에서 작업을 업데이트하고 삭제하는 데 표시됩니다.
업데이트나 삭제 작업 중 트랜잭션의 논리적 시작 이후로 행이 업데이트 또는 삭제된 것이 확인되면 작업은 오류 41302가 발생하며 실패하게 됩니다. 오류 41302의 메시지는 "현재 트랜잭션에서 이 트랜잭션이 시작된 이후로 업데이트된 레코드를 업데이트하려고 시도했습니다. 트랜잭션이 중단되었습니다."입니다.
이 오류는 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)를 통한 명시적 잠금은 지원되지 않습니다.