| PostgreSQL 8.0.26 문서 | ||||
|---|---|---|---|---|
| 범퍼카 토토 : 문서 : 8.0 : 범퍼카 토토 제어 | 빠르게 뒤로 | 12장. 동시성 제어 | 빨리 감기 | 다음 | 
그SQL표준은 정의합니다 세 가지 현상에 따른 네 가지 수준의 트랜잭션 격리 이는 동시 트랜잭션 간에 방지되어야 합니다. 이것들 바람직하지 않은 현상은 다음과 같습니다.
4개의 거래 격리 수준과 해당 동작은 다음에 설명되어 있습니다.테이블 12-1.
표 12-1.SQL토토 격리 수준
| 격리 수준 | 더티 읽기 | 반복 불가능한 읽기 | 팬텀 읽기 | 
|---|---|---|---|
| 커밋되지 않은 읽기 | 가능 | 가능 | 가능 | 
| 읽기 커밋 | 불가능 | 가능 | 가능 | 
| 반복 읽기 | 불가능 | 불가능 | 가능 | 
| 직렬화 가능 | 불가능 | 불가능 | 불가능 | 
에PostgreSQL, 할 수 있어요 네 가지 표준 토토 격리 수준 중 하나를 요청합니다. 그러나 내부적으로는 두 가지 격리 수준만 있습니다. 이는 읽기 커밋 및 직렬화 가능 수준에 해당합니다. 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이다 진정한 직렬성을 보장하기에는 충분하지 않으며 실제로PostgreSQL의 직렬화 가능 모드보장하지 않음 이러한 의미에서 직렬화 가능한 실행. 예를 들어, 테이블을 고려하십시오마이탭, 처음에는 포함
클래스 | 가치 
-----+-------
     1 |    10
     1 |    20
     2 |   100
     2 |   200
      직렬화 가능한 트랜잭션 A가 계산한다고 가정합니다.
WHERE 클래스 = 1인 mytab에서 SUM(값) 선택;
그런 다음 결과(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그렇습니다 조건자 잠금을 구현하지 않으며 우리가 아는 한 다른 프로덕션 DBMS도 마찬가지입니다.
비직렬화 가능성이 있는 경우 실행은 실제 위험이므로 문제는 다음을 통해 예방할 수 있습니다. 명시적 잠금을 적절하게 사용합니다. 추가 논의 다음 섹션에 나타납니다.
| [1] | 
       기본적으로 술어 잠금 시스템은 팬텀을 방지합니다. MVCC는 기록된 내용을 제한하여 읽는 반면, MVCC는 읽는 내용을 제한하여 읽습니다.  | 
  
| 범퍼카 토토 : 문서 : 8.0 : 범퍼카 토토 제어 | 집 | 다음 | 
| 동시성 제어 | 위로 | 명시적 잠금 |