2.1 커밋되지 않은 읽기

"트랜잭션 격리 수준"은 트랜잭션의 병렬 실행 중에 발생하는 위 유형의 데이터 불일치의 전부 또는 일부로부터 DBMS의 내부 메커니즘(즉, 특별한 프로그래밍이 필요하지 않음)이 제공하는 보호 정도를 나타냅니다. SQL-92 표준은 네 가지 격리 수준의 규모를 정의합니다.

  • 커밋되지 않은 읽기
  • 커밋 읽기
  • 반복 읽기
  • 직렬화 가능

첫 번째는 가장 약하고 마지막은 가장 강하며 각 후속 항목에는 이전 항목이 모두 포함됩니다.

가장 낮은(첫 번째) 격리 수준입니다. 여러 병렬 트랜잭션이 동일한 테이블 행을 수정하려고 하면 마지막 행은 성공적으로 완료된 트랜잭션의 전체 집합에 의해 결정되는 값을 갖게 됩니다. 이 경우 논리적으로 일치하지 않는 데이터뿐만 아니라 아직 변경 사항이 기록되지 않은 데이터도 읽을 수 있습니다.

이 격리 수준을 구현하는 일반적인 방법은 변경 명령이 실행되는 동안 데이터를 잠그는 것입니다. 이렇게 하면 병렬로 실행되는 동일한 행에 대한 수정 명령이 실제로 순차적으로 실행되고 변경 사항이 손실되지 않습니다. 읽기 전용 트랜잭션은 이 격리 수준에서 차단되지 않습니다.

2.2 커밋된 읽기

대부분의 산업용 DBMS, 특히 Microsoft SQL Server, PostgreSQL 및 Oracle은 기본적으로 이 수준을 사용합니다. 이 수준에서는 초안 "더티" 읽기에 대한 보호가 제공되지만 한 트랜잭션이 작동하는 동안 다른 트랜잭션이 성공적으로 완료되고 변경 사항이 수정될 수 있습니다. 결과적으로 첫 번째 트랜잭션은 다른 데이터 세트와 함께 작동합니다.

전체 읽기의 구현은 차단 또는 버전 관리의 두 가지 접근 방식 중 하나를 기반으로 할 수 있습니다.

읽을 수 있고 변경 가능한 데이터를 차단합니다.

쓰기 트랜잭션은 읽기 커밋 수준 이상에서 동작하는 읽기 트랜잭션에 대한 변경 가능한 데이터를 완료될 때까지 차단하여 "더티" 읽기를 방지하고 읽기 트랜잭션에 의해 잠긴 데이터는 작업 완료 후 즉시 해제된다는 사실로 구성됩니다. SELECT(따라서 "반복 불가능한 읽기" 상황은 지정된 격리 수준에서 발생할 수 있습니다.)

동시에 변경되는 여러 버전의 행을 저장합니다.

행이 변경될 때마다 DBMS는 이 행의 새 버전을 생성하며, 데이터를 변경한 트랜잭션은 계속 작동하는 반면 다른 "읽기" 트랜잭션은 마지막 커밋된 버전을 반환합니다. 이 접근 방식의 장점은 차단을 방지하기 때문에 더 빠르다는 것입니다. 그러나 첫 번째 버전과 비교하여 행 버전을 저장하는 데 사용되는 훨씬 더 많은 RAM 소비가 필요합니다.

또한 여러 트랜잭션이 병렬로 데이터를 변경하는 경우 여러 동시 트랜잭션이 동일한 데이터를 일관되지 않게 변경하는 상황을 만들 수 있습니다(잠금이 없으므로 이러한 일이 발생하는 것을 막을 수 없습니다). 그런 다음 먼저 커밋하는 트랜잭션은 기본 데이터베이스에 변경 사항을 저장하고 나머지 병렬 트랜잭션은 커밋할 수 없습니다(이로 인해 첫 번째 트랜잭션의 업데이트가 손실됨). 이러한 상황에서 DBMS가 할 수 있는 유일한 조치는 나머지 트랜잭션을 롤백하고 "레코드가 이미 변경되었습니다"라는 오류 메시지를 발행하는 것입니다.

특정 구현 방법은 DBMS 개발자가 선택하며 경우에 따라 사용자 정의할 수 있습니다. 따라서 기본적으로 MS SQL은 잠금을 사용하지만 (버전 2005 이상) READ_COMMITTED_SNAPSHOT데이터베이스 매개 변수를 설정할 때 버전 관리 전략으로 전환되며 Oracle은 초기에 버전 체계에 따라서만 작동합니다. Informix에서는 읽기 트랜잭션이 USELASTCOMMITTED가장 최근에 커밋된 데이터를 받도록 하는 구성 옵션(버전 11.1 기준)을 설정하여 읽기 트랜잭션과 쓰기 트랜잭션 간의 충돌을 방지할 수 있습니다.

2.3 반복 읽기

읽기 트랜잭션이 "보이지 않는" 수준은 이전에 읽은 데이터로 변경됩니다. 동시에 다른 트랜잭션은 종료될 때까지 현재 트랜잭션이 읽은 데이터를 변경할 수 없습니다.

공유 모드의 잠금은 트랜잭션의 모든 명령에서 읽은 모든 데이터에 적용되며 트랜잭션이 완료될 때까지 유지됩니다. 이렇게 하면 다른 트랜잭션이 보류 중인 트랜잭션에서 읽은 행을 수정하지 못합니다. 그러나 다른 트랜잭션은 현재 트랜잭션에 포함된 명령에 대한 검색 조건과 일치하는 줄 바꿈을 삽입할 수 있습니다. 명령문이 현재 트랜잭션에 의해 다시 시작되면 새 행을 가져와 팬텀 읽기가 발생합니다.

공유 잠금이 각 문이 끝날 때 해제되는 것이 아니라 트랜잭션이 끝날 때까지 유지된다는 점을 감안할 때 동시성의 정도는 격리 수준보다 낮습니다 READ COMMITTED. 따라서 불필요하게 이 이상의 트랜잭션 수준을 사용하는 것은 일반적으로 권장되지 않습니다.

2.4 직렬화 가능

최고 수준의 격리; 트랜잭션은 서로 완전히 격리되어 있으며 각각은 병렬 트랜잭션이 없는 것처럼 실행됩니다. 동시 트랜잭션이 "팬텀 읽기" 효과의 영향을 받지 않는 것은 이 수준에서만 가능합니다.

2.5 실제 DBMS에서 트랜잭션 격리 지원

트랜잭션 DBMS는 항상 네 가지 수준을 모두 지원하지 않으며 추가 수준을 도입할 수도 있습니다. 절연 제공에는 다양한 뉘앙스가 있습니다.

따라서 원칙적으로 Oracle은 트랜잭션 구현에서 "더티 읽기"를 제외하고 반복 읽기 수준 설정을 공식적으로 허용하지 않기 때문에 0 수준을 지원하지 않습니다. 즉, ( 기본적으로) Read committedSerializable. 동시에 개별 명령 수준에서 실제로 읽기 반복성을 보장합니다( SELECT첫 번째 트랜잭션의 명령이 데이터베이스에서 일련의 행을 선택하고 이때 병렬 두 번째 트랜잭션이 이러한 행 중 일부를 변경하면 첫 번째 트랜잭션에서 받은 결과 집합에는 두 번째 트랜잭션이 없는 것처럼 변경되지 않은 행이 포함됩니다. Oracle은 또한 에 해당하는 소위 READ-ONLY트랜잭션을 지원 Serializable하지만 데이터 자체를 변경할 수는 없습니다.

그리고 Microsoft SQL Server는 네 가지 표준 트랜잭션 격리 수준을 모두 지원하고 추가로 SNAPSHOT 수준을 지원합니다. 이 수준에서는 트랜잭션이 실행되기 전에 커밋된 데이터 상태와 자체 변경 사항을 볼 수 있습니다. 시작 시 DB 데이터의 스냅샷을 수신하고 작업합니다. 직렬화와의 차이점은 잠금이 사용되지 않는다는 점이지만 결과적으로 동시 트랜잭션이 이전에 동일한 데이터를 변경한 경우 변경 사항 커밋이 불가능할 수 있습니다. 이 경우 두 번째 트랜잭션은 실행을 시도할 때 COMMIT오류 메시지를 표시하고 취소됩니다.