이 문서는 지원되지 않는 버전의 PostgreSQL을위한 것입니다.
당신은에 대해 같은 페이지를 보려고 할 수 있습니다PostgreSQL : 문서 : 17 : 13.2. 무지개 토토 격리버전 또는 위에 나열된 다른 지원 버전 중 하나입니다.

13.2. 거래 격리

theSQL표준 정의 트랜잭션 격리의 4 가지 수준. 가장 엄격한 것은 직렬화 가능하며 단락에서 표준에 의해 정의됩니다. 일련의 직렬화 가능한 모든 실행이 거래는 실행과 동일한 효과를 생성하도록 보장됩니다. 한 번에 하나씩 순서대로 하나. 다른 세 가지 수준은입니다 사이의 상호 작용으로 인한 현상 측면에서 정의됩니다 각 레벨에서 발생하지 않아야하는 동시 트랜잭션. 그만큼 표준 노트는 직렬화 가능의 정의로 인해 이러한 현상 중 그 수준에서 가능합니다. (이것은 거의 아닙니다 놀랍게도 - 거래의 효과가 한 번에 하나씩 실행 된 것과 일치하면 어떻게 볼 수 있습니까? 상호 작용으로 인한 현상?)

다양한 수준에서 금지되는 현상은 다음과 같습니다.

더러운 읽기

트랜잭션은 동시에 작성된 데이터를 읽습니다 커밋되지 않은 거래.

반복 할 수없는 읽기

트랜잭션은 이전에 읽은 데이터를 다시 읽습니다 데이터가 다른 트랜잭션에 의해 수정되었음을 발견합니다 (처음 읽은 이후로 커밋 된).

Phantom Read

트랜잭션은 쿼리 세트를 다시 실행합니다 검색 조건을 만족시키고 세트를 찾는 행 다른 때문에 조건을 만족시키는 줄의 최근에 커뮤니케이션 거래.

4 개의 트랜잭션 격리 수준과 해당 행동은에 설명되어 있습니다.표 13-1.

표 13-1. 기준SQL거래 격리 수준

격리 레벨 더러운 읽기 반복 할 수없는 읽기 Phantom Read
커밋되지 않은 읽기 가능 가능 가능
Committed 불가능 가능 가능
반복 가능한 읽기 불가능 불가능 가능
SERIALIZALE 가능하지 않음 불가능 불가능

inPostgreSQL, 가능합니다 4 개의 표준 트랜잭션 격리 수준 중 하나를 요청하십시오. 그러나 내부적으로는 3 개의 별개의 격리 수준 만 있으며 커밋 된 레벨, 반복 가능한 읽기, 및 직렬화 가능. 레벨을 선택할 때는 커밋되지 않은 읽기를 읽습니다 정말로 읽히고 팬텀 리드가 불가능합니다. 그만큼PostgreSQL구현 반복 가능한 읽기, 실제 격리 수준이 더 엄격 할 수 있습니다. 선택한 것보다. 이것은 SQL 표준에 의해 허용됩니다 4 개의 격리 수준은 어떤 현상이 어떤 현상이되어서는 안되는지를 정의합니다 발생하면 어떤 현상이 발생 해야하는지 정의하지 않습니다. 그만큼 이유PostgreSQL만 세 가지 격리 수준을 제공하는 것은 이것이 유일한 합리적이라는 것입니다. 표준 격리 레벨을 멀티 디렉션에 매핑하는 방법 동시성 제어 아키텍처. 사용 가능한 동작 격리 수준은 다음 하위 섹션에 자세히 설명되어 있습니다.

거래의 거래 격리 수준을 설정하려면 사용 명령세트 거래.

13.2.1. 헌신적 인 격리를 읽으십시오 수준

Committed 읽기기본값입니다 격리 수준에서PostgreSQL. 거래가이 격리 수준을 사용하면 aselect쿼리 (a업데이트/공유조항) 앞에 커밋 된 데이터 만 볼 수 있습니다 쿼리가 시작되었습니다. 커밋되지 않은 데이터 나 변경을 볼 수 없습니다 동시 트랜잭션에 의해 쿼리 실행 중에 커밋. ~ 안에 효과, Aselect쿼리에는 스냅 샷이 보입니다 즉시 데이터베이스 중 쿼리가 실행되기 시작합니다. 하지만,select효과가 보입니다 자체 거래 내에서 실행 된 이전 업데이트 중 그들은 아직 헌신적이지 않았지만. 또한 두 가지에 유의하십시오 연속select명령을 볼 수 있습니다 다른 데이터는 단일 내에 있지만 다른 트랜잭션이 변경되는 경우 거래가 변경됩니다 첫 번째 실행select.

업데이트, 삭제, 선택을 선택하십시오 업데이트공유 선택명령은와 동일하게 행동합니다.selectin 대상 행 검색 조건 : 대상 만 찾을 수 있습니다. 명령 시작 시간에 따라 커밋 된 행. 하지만, 이러한 대상 행은 이미 업데이트되었거나 삭제되었을 수 있습니다. 또는 잠긴) 다른 동시 거래에 의해 설립하다. 이 경우 업데이트가 커밋 또는 롤백을 위해 트랜잭션을 최초로 업데이트합니다 ( 아직 진행 중). 첫 번째 업데이트가 롤백되면, 그것 효과가 무효화되고 두 번째 업데이트는 다음과 같이 진행할 수 있습니다. 원래 발견 된 행을 업데이트합니다. 첫 번째 업데이터 인 경우 커밋, 두 번째 업데이터는 첫 번째 경우 행을 무시합니다. Updater는 삭제했습니다. 그렇지 않으면 적용하려고합니다. 행의 업데이트 버전으로 작동합니다. 검색 명령 조건 (여기서조항)는 업데이트 된 버전의 행은 여전히 ​​검색 조건과 일치합니다. 그렇다면 두 번째 업데이트는 업데이트 된 버전을 사용하여 작동을 진행합니다 행의. 의 경우선택 업데이트and공유 선택,이 잠긴 행의 업데이트 버전임을 의미합니다. 클라이언트에게 반환.

위 규칙으로 인해 업데이트가 가능합니다. 일관되지 않은 스냅 샷을 보도록 명령 : 효과를 볼 수 있습니다. 동일한 행에 동시 업데이트 명령이 시도 중입니다. 업데이트하려면 해당 명령의 영향이 보이지 않습니다. 데이터베이스의 다른 행. 이 행동은 읽기를 저지른 것입니다 복잡한 검색과 관련된 명령에 부적합한 모드 정황; 그러나 더 간단한 경우에 적합합니다. 을 위한 예를 들어, 은행 잔액을 거래로 업데이트하는 것을 고려하십시오 좋다:

시작;
업데이트 계정 설정 밸런스 = 밸런스 + 100.00 여기서 acctnum = 12345;
업데이트 계정 설정 밸런스 = 밸런스 -100.00 여기서 acctnum = 7534;
저지르다;

그러한 두 거래가 동시에 변경하려고한다면 계정 잔액 12345, 우리는 분명히 두 번째를 원합니다 계정의 업데이트 된 버전으로 시작하는 거래 열. 각 명령은 미리 결정된 것만 영향을 미치기 때문입니다 행, 행의 업데이트 된 버전을 보자 번거로운 불일치를 만듭니다.

더 복잡한 사용으로 인해 읽기가 바람직하지 않은 결과를 얻을 수 있습니다 커밋 된 모드. 예를 들어, 고려하십시오.삭제존재하는 데이터에서 작동하는 명령 다른 사람의 제한 기준에서 추가 및 제거 명령, 예를 들어, 가정웹 사이트is 가있는 2 열 테이블웹 사이트. hits동등한9and10:

시작;
업데이트 웹 사이트 세트 hits = hits + 1;
- 다른 세션에서 실행 : hits = 10 인 웹 사이트에서 삭제;
저지르다;

the삭제조차도 영향을 미치지 않습니다 가 있지만웹 사이트. hits = 10전후에 행업데이트. 이것 업데이트 전 행 값이 발생하기 때문에 발생합니다9건너 뛰고업데이트완성 및삭제잠금을 얻고 새 행 값은 아니오입니다 더 길게10그러나11, 더 이상 기준과 일치하지 않습니다.

read commited mode가 새로 각 명령을 시작하기 때문에 그에 대한 모든 트랜잭션이 포함 된 스냅 샷 동일한 거래에서 즉시, 후속 명령이 표시됩니다 커밋 된 동시 거래의 효과 사례. 위의 문제점은 A인지 여부입니다.단일명령은 절대적으로 본다 데이터베이스의 일관된보기.

Read Commited에 의해 제공되는 부분 트랜잭션 격리 모드는 많은 응용 프로그램에 적합 하며이 모드는 빠릅니다. 사용하기 간단합니다. 그러나 모든 경우에 충분하지는 않습니다. 복잡한 쿼리 및 업데이트를 수행하는 응용 프로그램에는 필요할 수 있습니다 읽은 것보다 데이터베이스의보다 엄격하게 일관된보기 커밋 된 모드 제공.

13.2.2. 반복 가능한 읽기 격리 수준

the반복 가능한 읽기분리 레벨 거래가 시작되기 전에 저지른 데이터 만 본다. 결코 커밋되지 않은 데이터 나 변경 중에 커밋 된 변경 사항이 나타납니다 동시 거래에 의한 거래 실행. (그러나, Query는 이전 업데이트가 실행 된 효과를 봅니다. 자체 거래는 아직 커밋되지 않았음에도 불구하고.) 이것은에 의해 요구되는 것보다 더 강력한 보증입니다.SQL이를위한 표준 분리 수준,에 설명 된 모든 현상을 방지합니다.테이블 13-1. 위에서 언급했듯이, 이것은 구체적으로 허용됩니다 표준 만 설명하는 표준최소각각 보호 격리 수준은 제공해야합니다.

이 레벨은 쿼리에서 저지른 읽기와 다릅니다. 반복 가능한 읽기 트랜잭션에서 시작거래, 시작 시점이 아닙니다 트랜잭션 내 현재 쿼리 따라서 연속selecta 내 명령단일거래를 참조하십시오 데이터, 즉 다른 거래의 변경 사항이 보이지 않습니다. 그들 자신의 거래가 시작된 후 커밋되었습니다.

이 레벨을 사용한 응용 프로그램은 재 시도해야합니다 직렬화 실패로 인한 거래.

업데이트, 삭제, 선택 업데이트공유 선택명령은와 동일하게 행동합니다.selectin 대상 행 검색 조건 : 대상 만 찾을 수 있습니다. 트랜잭션 시작 시간에 따라 커밋 된 행. 그러나 이러한 대상 행은 이미 업데이트되었을 수 있습니다 (또는 다른 동시 거래에 의해 삭제 또는 잠금) 시간이 발견됩니다. 이 경우 반복 가능한 읽기 트랜잭션 첫 번째 업데이트 트랜잭션이 커밋 또는 롤을 기다릴 때까지 기다립니다. 뒤로 (아직 진행중인 경우). 첫 번째 업데이트가 굴리는 경우 뒤로, 그 효과가 부정되고 반복 가능한 읽기 트랜잭션은 원래 발견 된 행을 업데이트하여 진행할 수 있습니다. 그러나 첫 번째 업데이트가 커밋하는 경우 (그리고 실제로 업데이트되었거나 잠긴 것이 아니라 행을 삭제했습니다. 트랜잭션은 메시지와 함께 롤백됩니다

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

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

응용 프로그램 이이 오류 메시지를 받으면해야합니다 현재 거래를 중단하고 전체 거래를 다시 시도하십시오 처음부터. 두 번째로, 거래 이전에 커밋 된 변화를 초기의 일부로 볼 것입니다. 데이터베이스보기이므로 사용하는 데 논리적 충돌이 없습니다. 새로운 행의 새 버전은 새로운 것의 시작점으로 거래의 업데이트.

거래 만 업데이트해야 할 수도 있습니다 retried; 읽기 전용 트랜잭션에는 직렬화가 없습니다 갈등.

반복 가능한 읽기 모드는 엄격한 보증을 제공합니다 각 트랜잭션은 데이터베이스의 완전히 안정적인 관점을 보게됩니다. 그러나이 견해가 반드시 일관성이있는 것은 아닙니다 동시의 일부 직렬 (한 번에 하나씩) 실행 같은 수준의 거래. 예를 들어, 읽기 전용 이 수준에서의 거래는 제어 기록이 업데이트 될 수 있습니다. 배치가 완료되었음을 보여 주지만not세부 레코드 중 하나를 참조하십시오 이전에 읽기 때문에 배치의 논리적 인 부분입니다. 제어 레코드의 개정. 비즈니스를 시행하려는 시도 이 격리 수준에서 실행되는 거래 규칙은 명시 적 잠금 장치를 신중하게 사용하지 않고 올바르게 작동 할 가능성이 높습니다. 상충되는 거래를 차단하려면

참고 :이전postgresql버전 9.1, 요청 일련의 트랜잭션 격리 수준이 제공됩니다 여기에 묘사 된 동일한 동작. 유지하기 위해 레거시 직렬화 가능한 동작, 반복 가능한 읽기가 이제 있어야합니다 요청.

13.2.3. 직렬화 가능한 분리 수준

theSERIALIZALE분리 레벨 가장 엄격한 트랜잭션 격리를 제공합니다. 이 수준 트랜잭션이 마치 마치 마치 마치 일련의 거래 실행을 에뮬레이트합니다 평온한 것이 아니라 연속적으로 실행되었습니다 동시에. 그러나 반복 가능한 읽기 레벨과 마찬가지로 이 레벨을 사용하는 응용 프로그램은 다시 시도해야합니다 직렬화 실패로 인한 거래. 사실, 이것은입니다 격리 레벨은 반복 가능한 읽기와 정확히 동일합니다 그것을 만들 수있는 조건을 모니터링한다는 점을 제외하고 일련의 일련의 거래 세트의 실행 가능한 모든 연재물과 일치하지 않는 방식으로 행동하십시오 (하나는 하나 한 번에) 해당 거래 실행. 이 모니터링 그 선물 이외의 차단을 소개하지 않습니다 반복 가능한 읽기이지만 모니터링에 약간의 오버 헤드가 있습니다. 그리고 a를 유발할 수있는 조건의 탐지직렬화 이상a 트리거직렬화 실패.

예를 들어 테이블을 고려Mytab, 처음 포함 :

클래스 | 값 
-------+-------
     1 |    10
     1 |    20
     2 |   100
     2 |   200

직렬화 가능한 트랜잭션이 계산된다고 가정합니다.

mytab에서 sum (value)을 선택하여 클래스 = 1;

그런 다음 결과 (30)을로 삽입합니다.value새 행으로클래스 = 2. 동시에, 직렬화 가능한 트랜잭션 B 계산 :

mytab에서 sum (value)을 선택하여 클래스 = 2;

결과 300을 얻습니다. 와 함께클래스 = 1. 그런 다음 두 거래 모두 커밋을 시도합니다. 어느 쪽이든 반복 가능한 읽기 격리에서 트랜잭션이 진행되었습니다 레벨, 둘 다 커밋 할 수 있습니다. 그러나 없기 때문에 일련의 실행 순서는 결과를 사용하여 결과와 일치합니다 직렬화 가능한 거래를 통해 하나의 거래가 커밋 할 수 있습니다 그리고이 메시지로 다른 사람을 뒤로 굴립니다.

오류 : 트랜잭션 간의 읽기/쓰기 종속성으로 인해 액세스를 일차화 할 수 없습니다

이것은 A가 B 전에 실행 된 경우 B가 300이 아닌 합계 330 및 마찬가지로 다른 순서를 계산했습니다. A에 의해 계산 된 다른 합계를 초래했을 것입니다.

진정한 직렬화 가능성을 보장하려면PostgreSQL용도술어 잠금쓰기가 언제 발생했는지 결정할 수있는 잠금 동시의 이전 읽기 결과에 미치는 영향 거래, 먼저 실행되었다. 안에PostgreSQL이 자물쇠는 원인이되지 않습니다 차단과 따라서nota 이중 자물쇠. 그것들은 의존성을 식별하고 플래그하는 데 사용됩니다 동시 직렬화 가능한 거래 조합은 직렬화 이상으로 이어질 수 있습니다. 대조적으로, 원하는 헌신적이거나 반복 가능한 읽기 트랜잭션 데이터 일관성이 다른 사용자를 차단할 수있는 전체 테이블 그 테이블, 또는 사용할 수 있습니다선택을 선택하십시오 업데이트또는공유 선택다른 트랜잭션을 차단할 수있을뿐만 아니라 디스크를 유발할 수 있습니다 입장.

술어 잠금 장치​​PostgreSQL, 대부분의 다른 데이터베이스와 마찬가지로 시스템은 실제로 트랜잭션에 의해 액세스 된 데이터를 기반으로합니다. 이것들은에 나타날 것입니다.pg_locksa 시스템보기모드ofsireadlock. 특정 자물쇠가 획득했습니다 쿼리 실행은 쿼리가 사용하는 계획에 따라 다릅니다. 그리고 다수의 더 미세한 잠금 잠금 장치 (예 : 튜플 잠금 장치)가있을 수 있습니다 더 적은 수의 거친 자물쇠로 결합 (예 : 페이지 잠금 장치) 거래 과정에서 메모리는 자물쇠를 추적하는 데 사용됩니다. 에이읽기 오직트랜잭션은 Siread 잠금 장치를 해제 할 수 있습니다 완료하기 전에 충돌이 여전히 없음을 감지하면 직렬화 이상으로 이어질 수 있습니다. 사실은,읽기 전용거래가 종종있을 것입니다 스타트 업에서 그 사실을 확립하고 복용을 피할 수 있습니다. 술어 잠금. 명시 적으로 요청하면SERIALIZALE 읽기 전용 연기 가능거래, 이 사실을 확립 할 수있을 때까지 차단됩니다. (이것은입니다.전용케이스 위치 직렬화 가능한 트랜잭션은 차단되지만 반복 가능한 읽기 반면에, 거래는 종종 Siread 자물쇠가 필요합니다. 겹치는 읽기 전까지는 거래 커밋을 지나서 유지합니다 트랜잭션 작성 완료.

직렬화 가능한 트랜잭션의 일관된 사용은 단순화 될 수 있습니다 개발. 일련의 동시에 보장 직렬화 가능한 거래는 한 번에 하나씩 달리면 서면대로 단일 거래는 그 자체로 달리면, 당신은 그것이 할 것이라고 확신 할 수 있습니다. 직렬화 가능한 트랜잭션의 혼합에서도 올바른 것도 있습니다 다른 거래에 대한 정보없이 할 수도 있습니다. 이것을 사용하는 환경이 중요합니다 기술은 일반화 된 직렬화 방법을 가지고 있습니다 실패 (항상 sqlstate 값으로 반환됩니다 '40001'), 정확히 어느 것을 예측하기가 매우 어려울 것이기 때문입니다. 거래는 읽기/쓰기 종속성에 기여할 수 있습니다 직렬화 이상을 방지하기 위해 롤백해야합니다. 읽기/쓰기 종속성의 모니터링에는 비용이 있습니다. a로 종료되는 트랜잭션의 재시작 직렬화 실패이지만 비용과 균형을 이루었습니다 명시 적 잠금 장치 사용과 관련된 차단 및업데이트 선택또는선택 공유 용, 직렬화 가능한 트랜잭션이 가장 좋습니다 일부 환경에 대한 성능 선택.

직렬화 가능에 의존 할 때 최적의 성능 동시성 통제를위한 거래, 이러한 문제는 이루어져야합니다 존경받는:

  • 거래 선언으로읽기 오직가능하면.

  • a를 사용하여 활성 연결 수를 제어합니다 필요한 경우 연결 풀. 이것은 항상 중요합니다 성능 고려 사항이지만 특히 가능합니다 직렬화 가능한 바쁜 시스템에서 중요합니다 업무.

  • 필요한 것보다 단일 트랜잭션에 더 많이 넣지 마십시오. 무결성 목적.

  • 연결을 매달려 두지 마십시오"트랜잭션의 유휴"보다 길다 필요한.

  • 명시 적 잠금 제거,선택을 선택하십시오 업데이트공유 선택보호로 인해 더 이상 필요하지 않은 곳 직렬화 가능한 거래에 의해 제공됩니다.

  • 시스템이 여러 페이지 레벨을 결합해야 할 때 술어 잠금 장치는 단일 관계 수준의 술어 잠금 장치로 잠금됩니다 술어 잠금 테이블은 메모리가 부족하기 때문에 직렬화 실패 속도의 증가가 발생할 수 있습니다. 당신은 증가하여 이것을 피할 수 있습니다max_pred_locks_per_transaction.

  • 순차적 스캔은 항상 필요합니다 관계 수준의 술어 잠금. 결과가 발생할 수 있습니다 직렬화 실패율 증가. 도움이 될 수 있습니다 감소로 인덱스 스캔 사용을 장려하기 위해random_page_cost및/또는 증가CPU_TUPLE_COST. 트랜잭션 롤백의 감소와 쿼리 실행의 전반적인 변경에 비해 다시 시작됩니다 시간.