그SQL표준 정의 세 가지 현상에 따른 네 가지 수준의 트랜잭션 격리 이는 동시 트랜잭션 간에 방지되어야 합니다. 이것들 바람직하지 않은 현상은 다음과 같습니다.
네 가지 거래 격리 수준과 해당 동작은 다음에 설명되어 있습니다.테이블 12-1.
표 12-1.SQL사설 토토 격리 수준
| 격리 수준 | 더티 읽기 | 반복 불사설 토토 읽기 | 팬텀 읽기 |
|---|---|---|---|
| 커밋되지 않은 읽기 | 가능 | 가능 | 가능 |
| 읽기 커밋 | 불가능 | 가능 | 가능 |
| 반복 읽기 | 불가능 | 불가능 | 가능 |
| 직렬화 가능 | 불가능 | 불가능 | 불가능 |
에포스트그레SQL, 할 수 있어요 네 가지 표준 사설 토토 격리 수준 중 하나를 요청합니다. 그러나 내부적으로는 두 가지 격리 수준만 있습니다. 이는 읽기 커밋 및 직렬화 가능 수준에 해당합니다. Read Uncommitted 수준을 선택하면 실제로 Read가 표시됩니다. 커밋되었으며 반복 읽기를 선택하면 실제로 직렬화 가능하므로 실제 격리 수준은 다음보다 엄격할 수 있습니다. 당신이 선택하는 것. 이는 SQL 표준에서 허용됩니다. 격리 수준은 발생해서는 안되는 현상만을 정의합니다. 그들은 어떤 현상이 일어나야 하는지 정의하지 않습니다. 그 이유는PostgreSQL2개만 제공 격리 수준은 이것이 매핑하는 유일한 합리적인 방법이라는 것입니다. 다중 버전 동시성 제어에 대한 표준 격리 수준 건축. 사용 가능한 격리 수준의 동작은 다음과 같습니다. 다음 하위 섹션에서 자세히 설명합니다.
트랜잭션의 사설 토토 격리 수준을 설정하려면 다음을 사용하십시오. 명령SET 거래.
읽기 커밋됨기본값입니다 격리 수준PostgreSQL. 이 격리 수준에서 트랜잭션이 실행되면 a선택쿼리는 이전에 커밋된 데이터만 봅니다. 쿼리가 시작되었습니다. 커밋되지 않은 데이터나 변경 사항을 볼 수 없습니다. 동시 트랜잭션에 의한 쿼리 실행 중에 커밋됩니다. (그러나선택다음을 봅니다 자체 내에서 실행된 이전 업데이트의 효과 아직 커밋되지 않은 경우에도 트랜잭션이 발생합니다.) 효과, a선택쿼리가 스냅샷을 봅니다. 해당 쿼리가 시작되는 순간의 데이터베이스 달리다. 두 개의 연속적인 것을 주목하십시오.선택명령은 범위 내에 있더라도 다른 데이터를 볼 수 있습니다. 단일 사설 토토, 다른 사설 토토이 도중에 변경 사항을 커밋하는 경우 첫 번째 실행선택.
업데이트, 삭제, 선택 대상 업데이트및공유 선택명령은 다음과 동일하게 동작합니다선택에 대상 행 검색 조건: 대상 행만 찾습니다. 명령 시작 시간을 기준으로 커밋된 행입니다. 그러나, 이러한 대상 행은 이미 업데이트되었거나 삭제되었거나 잠긴) 다른 동시 트랜잭션에 의해 발견. 이 경우 업데이트할 예정인 업데이트 프로그램은 다음을 기다립니다. 커밋하거나 롤백하기 위해 먼저 트랜잭션을 업데이트합니다(해당되는 경우). 아직 진행 중입니다.) 첫 번째 업데이트 프로그램이 롤백되면 효과는 무효화되고 두 번째 업데이트는 계속 진행할 수 있습니다. 원래 발견된 행을 업데이트합니다. 첫 번째 업데이트인 경우 커밋하면 두 번째 업데이터는 첫 번째 업데이터가 행을 무시합니다. 업데이터가 삭제했습니다. 그렇지 않으면 적용을 시도합니다. 업데이트된 버전의 행에 대한 작업입니다. 검색 명령의 조건(어디절)을 재평가하여 업데이트된 버전이 있는지 확인합니다. 행은 여전히 검색 조건과 일치합니다. 그렇다면 두 번째 업데이터는 업데이트된 것부터 시작하여 작업을 진행합니다. 행의 버전입니다. (의 경우선택 업데이트용그리고공유 선택, 이는 잠긴 행의 업데이트된 버전임을 의미합니다. 클라이언트에게 반환됩니다.)
위의 규칙으로 인해 업데이트가 가능합니다. 일관되지 않은 스냅샷을 보는 명령: 효과를 볼 수 있습니다. 동일한 행에 영향을 미치는 동시 업데이트 명령 업데이트를 시도하고 있지만 업데이트의 효과가 표시되지 않습니다. 데이터베이스의 다른 행에 대한 명령. 이 행동은 다음과 관련된 명령에는 읽기 커밋 모드가 적합하지 않습니다. 복잡한 검색 조건. 그러나 그것은 딱 맞습니다. 더 간단한 경우. 예를 들어 은행 잔고 업데이트를 고려해 보세요. 다음과 같은 거래로
시작; UPDATE 계정 SET 잔액 = 잔액 + 100.00 WHERE acctnum = 12345; UPDATE 계정 SET 잔액 = 잔액 - 100.00 WHERE acctnum = 7534; 커밋;
두 개의 트랜잭션이 동시에 변경을 시도하면 계정 잔액 12345, 우리는 분명히 두 번째 잔액을 원합니다 계정의 업데이트된 버전에서 시작되는 거래 행. 각 명령은 미리 결정된 명령에만 영향을 미치기 때문에 행의 업데이트된 버전을 볼 수 있도록 하는 것은 그렇지 않습니다. 골치 아픈 불일치를 만들어냅니다.
커밋 읽기 모드에서는 각각의 새 명령이 다음으로 시작됩니다. 지금까지 커밋된 모든 트랜잭션을 포함하는 새로운 스냅샷 그 순간, 동일한 트랜잭션의 후속 명령은 커밋된 동시 트랜잭션의 효과를 확인하세요. 사건. 여기서 문제가 되는 점은 a 내에 있는지 여부입니다.단일명령이 보입니다 데이터베이스에 대한 절대적으로 일관된 보기입니다.
Read Committed가 제공하는 부분 트랜잭션 격리 모드는 많은 응용 프로그램에 적합하며 이 모드는 빠릅니다. 사용이 간단합니다. 그러나 복잡한 작업을 수행하는 응용 프로그램의 경우 쿼리 및 업데이트를 수행하려면 더 많은 정보를 보장해야 할 수도 있습니다. 읽기보다 데이터베이스에 대한 엄격하고 일관된 보기 커밋 모드가 제공됩니다.
레벨직렬화 가능제공 가장 엄격한 트랜잭션 격리. 이 레벨은 직렬을 에뮬레이트합니다. 트랜잭션 실행, 마치 트랜잭션이 하나 실행된 것처럼 동시에가 아닌 순차적으로. 그러나, 이 수준을 사용하는 애플리케이션은 재시도할 준비가 되어 있어야 합니다. 직렬화 실패로 인한 거래.
트랜잭션이 직렬화 가능 수준에 있을 때, a선택쿼리는 커밋된 데이터만 봅니다. 거래가 시작되기 전; 커밋되지 않은 것을 결코 볼 수 없습니다 사설 토토 실행 중에 커밋된 데이터 또는 변경 사항 동시 사설 토토. (그러나선택이전 업데이트의 효과가 표시됩니다. 비록 그렇지 않더라도 자체 트랜잭션 내에서 실행됩니다. 아직 커밋되었습니다.) 이는 읽기 커밋과 다릅니다.선택현재 스냅샷을 봅니다. 현재 시작 시점이 아닌 거래 시작 시점 트랜잭션 내에서 쿼리합니다. 따라서 연속적인선택단일 트랜잭션 내의 명령 항상 같은 데이터를 봅니다.
업데이트, 삭제, 선택 대상 업데이트및공유 선택명령은 다음과 동일하게 동작합니다선택에 대상 행 검색 조건: 대상 행만 찾습니다. 트랜잭션 시작 시간을 기준으로 커밋된 행입니다. 그러나 이러한 대상 행은 이미 업데이트되었을 수 있습니다(또는 삭제되거나 잠김)에 의해 다른 동시 트랜잭션에 의해 발견된 시간입니다. 이 경우 직렬화 가능한 트랜잭션은 첫 번째 업데이트 트랜잭션이 커밋되거나 롤될 때까지 기다립니다. 뒤로(아직 진행 중인 경우) 첫 번째 업데이터가 굴러가는 경우 뒤로 돌아가면 그 효과는 무효화되고 직렬화 가능 트랜잭션은 원래 발견된 행 업데이트를 진행할 수 있습니다. 그러나 첫 번째 업데이트 프로그램이 커밋(그리고 실제로 업데이트되거나 잠긴 것이 아니라 행을 삭제한 다음) 직렬화 가능 메시지와 함께 트랜잭션이 롤백됩니다.
오류: 동시 업데이트로 인해 액세스를 직렬화할 수 없습니다.
직렬화 가능한 트랜잭션은 수정하거나 잠글 수 없기 때문에 직렬화 후 다른 트랜잭션에 의해 변경된 행 거래가 시작되었습니다.
응용 프로그램이 이 오류 메시지를 받으면 현재 트랜잭션을 중단하고 전체를 다시 시도하십시오. 처음부터 거래. 두 번째로 통과한 것은, 트랜잭션은 이전에 커밋된 변경 사항을 트랜잭션의 일부로 간주합니다. 데이터베이스의 초기 보기이므로 논리적 충돌이 없습니다. 새 버전의 행을 시작점으로 사용하는 경우 새로운 거래의 업데이트입니다.
업데이트된 거래만 재시도해야 할 수도 있습니다. 읽기 전용 트랜잭션에는 직렬화가 적용되지 않습니다. 충돌.
직렬화 가능 모드는 다음을 엄격하게 보장합니다. 각 트랜잭션은 데이터베이스에 대해 완전히 일관된 보기를 봅니다. 그러나 애플리케이션을 다시 시도할 준비가 되어 있어야 합니다. 동시 업데이트로 인해 트랜잭션이 불가능할 때의 트랜잭션 연속 처형의 환상을 유지합니다. 비용부터 복잡한 트랜잭션을 다시 실행하는 것이 중요할 수 있으므로 이 모드는 트랜잭션 업데이트에 논리가 포함된 경우에만 권장됩니다. 읽기에서 잘못된 답을 줄 수도 있을 만큼 충분히 복잡합니다. 커밋 모드. 가장 일반적으로 직렬화 가능 모드가 필요합니다. 트랜잭션이 여러 개의 연속적인 명령을 실행할 때 데이터베이스의 동일한 보기를 확인해야 합니다.
의 직관적인 의미(및 수학적 정의)"직렬화 가능"실행이란 성공적으로 커밋된 두 개의 동시 트랜잭션은 모두 엄격하게 순차적으로 실행된 것으로 보입니다. 기타 — 먼저 발생한 것으로 보이는 것이 아닐 수도 있습니다. 미리 예측 가능합니다. 그것을 깨닫는 것이 중요하다 다음에 나열된 바람직하지 않은 행동을 금지합니다.표 12-1이다 진정한 직렬성을 보장하기에는 충분하지 않으며 실제로포스트그레SQL의 직렬화 가능 모드보장하지 않음 이러한 의미에서 직렬화 가능한 실행. 예를 들어, 테이블을 고려하십시오마이탭, 처음에는 포함
클래스 | 가치
-----+-------
1 | 10
1 | 20
2 | 100
2 | 200
직렬화 가능한 트랜잭션 A가 계산한다고 가정합니다.
SELECT SUM(값) FROM mytab WHERE 클래스 = 1;
그리고 결과(30)를 다음과 같이 삽입합니다.값다음 행에클래스= 2. 동시에 직렬화 가능 거래 B가 계산합니다.
SELECT SUM(값) FROM mytab WHERE 클래스 = 2;
결과 300을 얻고 새 행에 삽입합니다. 와 함께클래스= 1. 그러면 둘 다 트랜잭션이 커밋됩니다. 나열된 바람직하지 않은 동작이 없습니다. 발생했지만, 우리는 가질 수 없는 결과를 얻었습니다. 순서대로 연속적으로 발생했습니다. A가 이전에 처형했다면 B, B는 합이 300이 아닌 330으로 계산되었을 것이고, 마찬가지로 다른 주문을 하면 금액이 달라졌을 것입니다 A에 의해 계산됨
진정한 수학적 직렬성을 보장하려면 다음과 같습니다. 데이터베이스 시스템을 시행하는 데 필요함술어 잠금, 이는 다음을 의미합니다. 트랜잭션은 다음과 같은 행을 삽입하거나 수정할 수 없습니다. 와 일치함어디조건 다른 동시 사설 토토을 쿼리합니다. 예를 들어, 한 번 사설 토토 A가 쿼리를 실행했습니다.선택 ... WHERE 클래스 = 1, 술어 잠금 시스템은 트랜잭션 B를 금지합니다. A가 커밋될 때까지 클래스 1의 새 행을 삽입합니다.[1]그런 잠금 시스템은 구현하기가 복잡하고 극도로 모든 세션이 이를 인식해야 하므로 실행 비용이 많이 듭니다. 모든 동시 실행에 의해 실행되는 모든 쿼리의 세부 정보 거래. 그리고 이 큰 비용은 대부분 낭비됩니다. 실제로 대부분의 응용 프로그램은 이러한 종류의 작업을 수행하지 않습니다. 그러면 문제가 발생할 수 있습니다. (물론 위의 예는 다소 인위적이며 실제 소프트웨어를 나타내지 않을 가능성이 높습니다.) 이러한 이유로,PostgreSQL술어를 구현하지 않습니다. 잠금.
비직렬화 가능성이 있는 경우 실행은 실제 위험이므로 문제는 다음을 통해 예방할 수 있습니다. 명시적 잠금을 적절하게 사용합니다. 추가 논의 다음 섹션에 나타납니다.
| [1] |
기본적으로 술어 잠금 시스템은 팬텀을 방지합니다. MVCC는 기록된 내용을 제한하여 읽는 반면, MVCC는 읽는 내용을 제한하여 읽습니다. |