이 문서는 지원되지 않는 PostgreSQL 버전에 대한 것입니다.
다음에 대한 동일한 페이지를 보고 싶을 수도 있습니다.PostgreSQL : 문서 : 17 : 13.2. 무지개 토토 격리버전 또는 위에 나열된 다른 지원 버전 중 하나를 사용하세요.

13.2. 거래 격리

SQL표준 정의 세 가지 현상에 따른 네 가지 수준의 트랜잭션 격리 이는 동시 트랜잭션 간에 방지되어야 합니다. 이것들 바람직하지 않은 현상은 다음과 같습니다.

더러운 읽기

젠 토토은 동시 작업에 의해 작성된 데이터를 읽습니다. 커밋되지 않은 젠 토토입니다.

반복할 수 없는 읽기

트랜잭션은 이전에 읽은 데이터를 다시 읽고 다른 트랜잭션에 의해 데이터가 수정되었음을 발견함 (초기 읽기 이후 커밋됨).

팬텀 읽기

트랜잭션은 다음 세트를 반환하는 쿼리를 다시 실행합니다. 검색 조건을 만족하고 해당 집합이 발견된 행 조건을 만족하는 행 중 다른 항목으로 인해 변경되었습니다. 최근에 커밋된 트랜잭션입니다.

네 가지 젠 토토 격리 수준과 해당 수준 동작은에 설명되어 있습니다.표 13-1.

표 13-1.SQL젠 토토 격리 수준

격리 수준 더티 읽기 반복할 수 없는 읽기 팬텀 읽기
커밋되지 않은 읽기 가능 가능 가능
읽기 커밋 불가능 가능 가능
반복 읽기 불가능 불가능 가능
직렬화 가능 불가능 불가능 불가능

포스트그레SQL할 수 있어요 네 가지 표준 젠 토토 격리 수준 중 하나를 요청합니다. 그러나 내부적으로는 두 가지 격리 수준만 있습니다. 이는 읽기 커밋 및 직렬화 가능 수준에 해당합니다. Read Uncommitted 수준을 선택하면 실제로 Read가 표시됩니다. 커밋되었으며 반복 읽기를 선택하면 실제로 직렬화 가능하므로 실제 격리 수준은 더 엄격할 수 있습니다. 당신이 선택한 것보다 이는 SQL 표준에서 허용됩니다. 네 가지 격리 수준은 어떤 현상이 발생해서는 안 되는지 정의할 뿐입니다. 어떤 현상이 일어나야 하는지 정의하지 않습니다. 는 그 이유는포스트그레SQL만 두 가지 격리 수준을 제공하는 것은 이것이 유일하게 합리적인 수준이라는 것입니다. 표준 격리 수준을 다중 버전에 매핑하는 방법 동시성 제어 아키텍처. 사용 가능한 동작 격리 수준은 다음 하위 섹션에 자세히 설명되어 있습니다.

트랜잭션의 젠 토토 격리 수준을 설정하려면 다음을 사용하십시오. 명령SET 거래.

13.2.1. 커밋된 격리 읽기 레벨

읽기 커밋됨기본값입니다 격리 수준포스트그레SQL. 트랜잭션이 이 격리 수준을 사용하는 경우, a선택쿼리(a 없음용 업데이트/공유절)은 이전에 커밋된 데이터만 봅니다. 쿼리가 시작되었습니다. 커밋되지 않은 데이터나 변경 사항을 볼 수 없습니다. 동시 트랜잭션에 의한 쿼리 실행 중에 커밋됩니다. 에서 효과, a선택쿼리가 스냅샷을 봅니다. 쿼리가 실행되기 시작하는 순간의 데이터베이스입니다. 그러나선택효과가 보입니다 자체 트랜잭션 내에서 실행된 이전 업데이트의 경우에도 아직 커밋되지는 않았지만. 또한 두 가지를 참고하세요 연속적인선택명령은 볼 수 있습니다 단일 데이터 내에 있더라도 서로 다른 데이터 젠 토토 중 다른 젠 토토이 변경 사항을 커밋하는 경우 첫 번째 실행선택.

업데이트, 삭제, 선택 대상 업데이트공유 선택명령은 다음과 동일하게 동작합니다선택에 대상 행 검색 조건: 대상 행만 찾습니다. 명령 시작 시간을 기준으로 커밋된 행입니다. 그러나, 이러한 대상 행은 이미 업데이트되었거나 삭제되었을 수 있습니다. 또는 잠긴 경우) 다른 동시 트랜잭션에 의해 발견. 이 경우 업데이트할 예정인 업데이트 프로그램은 다음을 기다립니다. 커밋하거나 롤백하기 위해 먼저 트랜잭션을 업데이트합니다(해당되는 경우). 아직 진행 중입니다.) 첫 번째 업데이트 프로그램이 롤백되면 효과는 무효화되고 두 번째 업데이트는 계속 진행할 수 있습니다. 원래 발견된 행을 업데이트합니다. 첫 번째 업데이트인 경우 커밋하면 두 번째 업데이터는 첫 번째 업데이터가 행을 무시합니다. 업데이터가 삭제했습니다. 그렇지 않으면 적용을 시도합니다. 업데이트된 버전의 행에 대한 작업입니다. 검색 명령의 조건(어디절)을 재평가하여 업데이트된 버전이 있는지 확인합니다. 행은 여전히 검색 조건과 일치합니다. 그렇다면 두 번째 업데이터는 업데이트된 버전을 사용하여 작업을 진행합니다. 행의. 의 경우선택 대상 업데이트그리고공유 선택, 이거 이는 잠긴 행의 업데이트된 버전임을 의미하며 고객에게 반환되었습니다.

위의 규칙으로 인해 업데이트가 가능합니다. 일관되지 않은 스냅샷을 보는 명령: 효과를 볼 수 있습니다. 시도하고 있는 동일한 행에 대한 동시 업데이트 명령 수 업데이트할 수 있지만 해당 명령의 효과는 표시되지 않습니다. 데이터베이스의 다른 행. 이 동작으로 인해 읽기 커밋이 이루어집니다. 복잡한 검색이 포함된 명령에는 적합하지 않은 모드 조건; 그러나 더 간단한 경우에는 적합합니다. 에 대한 예를 들어 거래를 통해 은행 잔고를 업데이트하는 것을 고려해 보세요. 좋아요:

시작;
UPDATE 계정 SET 잔액 = 잔액 + 100.00 WHERE acctnum = 12345;
UPDATE 계정 SET 잔액 = 잔액 - 100.00 WHERE acctnum = 7534;
커밋;

두 개의 트랜잭션이 동시에 변경을 시도하면 계정 잔액 12345, 우리는 분명히 두 번째 잔액을 원합니다 계정의 업데이트된 버전으로 시작하는 거래 행. 각 명령은 미리 결정된 명령에만 영향을 미치기 때문에 행의 업데이트된 버전을 볼 수 있도록 하는 것은 그렇지 않습니다. 골치 아픈 불일치를 만들어냅니다.

더 복잡하게 사용하면 읽기에서 바람직하지 않은 결과가 발생할 수 있습니다. 커밋 모드. 예를 들어 다음을 고려해보세요.삭제실행 중인 데이터에 대해 작동하는 명령 다른 사람에 의해 제한 기준에 추가되거나 제거되었습니다. 명령(예: 가정웹사이트은 2열 테이블website.hits같음9그리고10:

시작;
업데이트 웹사이트 SET 조회수 = 조회수 + 1;
-- 다른 세션에서 실행: DELETE FROM 웹사이트 WHERE 조회수 = 10;
커밋;

삭제심지어 효과가 없습니다. 하지만website.hits = 10앞과 뒤의 행업데이트. 이 업데이트 전 행 값 때문에 발생함9건너뛰고 다음 경우업데이트완료하고삭제잠금을 얻었으며 새 행 값은 no입니다. 더 이상10그러나11, 더 이상 기준과 일치하지 않습니다.

커밋 읽기 모드는 각 명령을 새로운 명령으로 시작하기 때문입니다. 해당 시점까지 커밋된 모든 젠 토토을 포함하는 스냅샷 즉시 동일한 젠 토토의 후속 명령이 표시됩니다. 커밋된 동시 젠 토토의 효과 사건. 위에서 문제가 되는 점은 a싱글명령은 절대적으로 데이터베이스의 일관된 보기.

Read Committed가 제공하는 부분 트랜잭션 격리 모드는 많은 응용 프로그램에 적합하며 이 모드는 빠릅니다. 사용이 간편합니다. 그러나 모든 경우에 충분하지는 않습니다. 복잡한 쿼리 및 업데이트를 수행하는 애플리케이션에는 다음이 필요할 수 있습니다. 읽기보다 데이터베이스에 대한 더 엄격하고 일관된 보기 커밋 모드가 제공됩니다.

13.2.2. 직렬화 가능 격리 레벨

직렬화 가능격리 수준 가장 엄격한 트랜잭션 격리를 제공합니다. 이 수준 마치 트랜잭션이 실행된 것처럼 직렬 트랜잭션 실행을 에뮬레이트합니다. 순차적으로 실행되기보다는 순차적으로 실행되었습니다. 동시에. 그러나 이 수준을 사용하는 응용 프로그램은 다음과 같아야 합니다. 직렬화로 인해 트랜잭션을 재시도할 준비가 되었습니다. 실패.

트랜잭션이 직렬화 가능 수준을 사용하는 경우, a선택쿼리는 커밋된 데이터만 볼 수 있습니다. 거래가 시작되기 전; 커밋되지 않은 것을 결코 볼 수 없습니다 트랜잭션 실행 중에 커밋된 데이터 또는 변경 사항 동시 트랜잭션. (그러나 쿼리에는 자체 내에서 실행된 이전 업데이트의 효과 아직 커밋되지 않은 경우에도 트랜잭션이 발생합니다.) 이는 직렬화 가능한 쿼리라는 점에서 Read Committed와 다릅니다. 트랜잭션은 시작 시점의 스냅샷을 확인합니다.거래, 처음부터 아님 트랜잭션 내의 현재 쿼리에 대한 정보입니다. 따라서 연속적인선택a 내의 명령싱글거래 동일 참조 즉, 다른 트랜잭션에 의해 변경된 내용을 볼 수 없습니다. 자체 트랜잭션이 시작된 후에 커밋되었습니다. (이 동작은 보고 애플리케이션에 이상적일 수 있습니다.)

업데이트, 삭제, 선택 대상 업데이트공유 선택명령은 다음과 동일하게 동작합니다선택에 대상 행 검색 조건: 대상 행만 찾습니다. 트랜잭션 시작 시간을 기준으로 커밋된 행입니다. 그러나 이러한 대상 행은 이미 업데이트되었을 수 있습니다(또는 삭제되거나 잠김)에 의해 다른 동시 트랜잭션에 의해 발견된 시간입니다. 이 경우 직렬화 가능한 트랜잭션은 첫 번째 업데이트 트랜잭션이 커밋되거나 롤될 때까지 기다립니다. 뒤로(아직 진행 중인 경우) 첫 번째 업데이터가 굴러가는 경우 뒤로 돌아가면 그 효과는 무효화되고 직렬화 가능 트랜잭션은 원래 발견된 행 업데이트를 진행할 수 있습니다. 그러나 첫 번째 업데이트 프로그램이 커밋(그리고 실제로 업데이트되거나 잠긴 것이 아니라 행을 삭제한 다음) 직렬화 가능 메시지와 함께 트랜잭션이 롤백됩니다.

오류: 동시 업데이트로 인해 액세스를 직렬화할 수 없습니다.

직렬화 가능한 트랜잭션은 수정하거나 잠글 수 없기 때문에 직렬화 후 다른 트랜잭션에 의해 변경된 행 거래가 시작되었습니다.

응용프로그램이 이 오류 메시지를 받으면, 현재 트랜잭션을 중단하고 전체 트랜잭션을 다시 시도합니다. 처음부터. 두 번째로 거래가 완료되었습니다. 이전에 커밋된 변경 사항이 초기 작업의 일부로 표시됩니다. 데이터베이스 보기이므로 사용 시 논리적 충돌이 없습니다. 행의 새 버전을 새 행의 시작점으로 사용 거래 업데이트.

거래 업데이트만 필요할 수 있다는 점에 유의하세요. 재시도; 읽기 전용 트랜잭션에는 직렬화가 적용되지 않습니다. 충돌.

직렬화 가능 모드는 다음을 엄격하게 보장합니다. 각 트랜잭션은 데이터베이스에 대해 완전히 일관된 보기를 봅니다. 그러나 애플리케이션을 다시 시도할 준비가 되어 있어야 합니다. 동시 업데이트로 인해 트랜잭션이 불가능할 때의 트랜잭션 연속 처형의 환상을 유지합니다. 비용부터 복잡한 트랜잭션을 다시 실행하는 것은 중요하고 직렬화가 가능합니다. 모드는 다음을 포함하는 트랜잭션을 업데이트하는 경우에만 권장됩니다. 잘못된 답을 줄 수도 있을 정도로 논리가 충분히 복잡함 커밋 읽기 모드에서. 가장 일반적으로 직렬화 가능 모드는 다음과 같습니다. 트랜잭션이 여러 번 연속적으로 실행될 때 필요합니다. 데이터베이스의 동일한 보기를 확인해야 하는 명령입니다.

13.2.2.1. 직렬화 가능 격리 진정한 직렬화 가능성과 비교

의 직관적인 의미(및 수학적 정의)"직렬화 가능"실행이란 성공적으로 커밋된 두 개의 동시 트랜잭션은 모두 엄격하게 순차적으로 실행된 것으로 보입니다. 기타 — 먼저 발생한 것으로 보이는 것이 아닐 수도 있습니다. 미리 예측할 수 있어야 합니다. 그것을 깨닫는 것이 중요하다 다음에 나열된 바람직하지 않은 행동을 금지합니다.표 13-1이다 진정한 직렬성을 보장하기에는 충분하지 않으며 실제로PostgreSQL의 직렬화 가능 모드보장하지 않음 이러한 의미에서 직렬화 가능한 실행. 예를 들어, 테이블을 고려하십시오마이탭, 처음에는 다음을 포함:

클래스 | 가치 
-----+-------
     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는 합계 330을 계산했을 것입니다. 300이고 마찬가지로 다른 주문도 다음과 같은 결과를 가져왔을 것입니다. A가 계산한 다른 합계.

진정한 수학적 직렬성을 보장하려면 다음과 같습니다. 데이터베이스 시스템을 시행하는 데 필요함술어 잠금, 즉 트랜잭션은 다음과 같은 행을 삽입하거나 수정할 수 없습니다. 와 일치함어디에서조건 다른 동시 젠 토토을 쿼리합니다. 예를 들어, 한 번 젠 토토 A가 쿼리를 실행했습니다.선택 ... WHERE 클래스 = 1, 술어 잠금 시스템은 트랜잭션 B를 금지합니다. A가 커밋될 때까지 클래스 1의 새 행을 삽입합니다.[1]그런 잠금 시스템은 구현하기가 복잡하고 극도로 모든 세션이 이를 인식해야 하므로 실행 비용이 많이 듭니다. 모든 동시 실행에 의해 실행되는 모든 쿼리의 세부 정보 거래. 그리고 이 큰 비용은 대부분 낭비됩니다. 실제로 대부분의 응용 프로그램은 이러한 종류의 작업을 수행하지 않습니다. 그러면 문제가 발생할 수 있습니다. (물론 위의 예는 다소 인위적이며 실제 소프트웨어를 나타내지 않을 가능성이 높습니다.) 이러한 이유로,PostgreSQL술어를 구현하지 않습니다. 잠금.

직렬화할 수 없는 가능성이 있는 경우 실행은 실제 위험이므로 문제는 다음을 통해 예방할 수 있습니다. 명시적 잠금을 적절하게 사용합니다. 추가 논의 다음 섹션에 나타납니다.

참고

[1]

기본적으로 술어 잠금 시스템은 팬텀을 방지합니다. MVCC는 기록된 내용을 제한하여 읽는 반면, MVCC는 읽는 내용을 제한하여 읽습니다.