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

13.2. 거래 격리

theSQL표준 정의 세 가지 현상 측면에서 4 가지 수준의 거래 격리 이는 동시 거래 사이에서 방지해야합니다. 이것들 바람직하지 않은 현상은 다음과 같습니다.

더러운 읽기

1Documentation6

반복 할 수없는 읽기

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

Phantom Read

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

11766_11857표 13-1.

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

격리 레벨 더러운 읽기 반복 할 수없는 읽기 Phantom Read
커밋되지 않은 읽기 가능 가능 가능
저지른 읽기 불가능 가능 가능
반복 가능한 읽기 불가능 불가능 가능
SERIALIZABLE 불가능 불가능 불가능

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

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

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

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

업데이트, 삭제, 선택을 선택하십시오 업데이트공유 선택명령은와 동일하게 행동합니다select대상 행 검색 조건 : 대상 만 찾을 수 있습니다. 명령 시작 시간에 따라 커밋 된 행. 하지만, 이러한 대상 행은 이미 업데이트되었거나 삭제되었을 수 있습니다. 또는 잠긴) 다른 동시 거래에 의해 설립하다. 이 경우 업데이트가 커밋 또는 롤백을 위해 트랜잭션을 최초로 업데이트합니다 ( 아직 진행 중). 첫 번째 업데이트가 롤백되면, 그것 효과가 무효화되고 두 번째 업데이트는 다음과 같이 진행할 수 있습니다. 원래 발견 된 행을 업데이트합니다. 첫 번째 업데이터 인 경우 커밋, 두 번째 업데이터는 첫 번째 경우 행을 무시합니다. 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. 직렬화 가능한 분리 수준

theSERIALIZALE격리 수준 가장 엄격한 트랜잭션 격리를 제공합니다. 이 수준 트랜잭션이 마치 마치 마치 마치 일련의 거래 실행을 에뮬레이트합니다 평온한 것이 아니라 연속적으로 실행되었습니다 동시에. 그러나이 수준을 사용하는 응용 프로그램은 있어야합니다 직렬화로 인한 거래를 재 시도 할 준비가되었습니다 실패.

트랜잭션이 직렬화 가능한 레벨을 사용하는 경우 Aselect쿼리는 데이터 만 보입니다 거래가 시작되기 전에; 커밋되지 않은 것을 보지 못합니다 트랜잭션 실행 중에 커밋 된 데이터 또는 변경 동시 거래. (그러나 쿼리는 이전 업데이트의 효과 자체 내에서 실행되었습니다 거래는 아직 커밋되지 않았지만 거래합니다.) 이것은 직렬화 가능한 쿼리에서 저지른 읽기와 다릅니다. 트랜잭션은 시작 시점에 스냅 샷을 봅니다.거래, 시작 시가 아닙니다 트랜잭션 내 현재 쿼리 따라서 연속selecta 내 명령단일거래를 참조하십시오 데이터, 즉 다른 거래의 변경 사항이 보이지 않습니다. 그 자체의 거래가 시작된 후 커밋되었습니다. (이것 행동은 신청서를보고하는 데 이상적입니다.)

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

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

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

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

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

직렬화 가능한 모드는 엄격한 보증을 제공합니다 각 트랜잭션은 데이터베이스의 전적으로 일관된 관점을 보게됩니다. 그러나 응용 프로그램은 다시 시도해야합니다 동시 업데이트가 불가능할 때 거래 직렬 실행의 환상을 유지하십시오. 비용 이후 복잡한 트랜잭션을 재조정하는 것은 일련화 할 수있는 중요 할 수 있습니다 트랜잭션 업데이트에 포함 된 경우에만 모드가 권장됩니다 그들이 잘못된 답을 줄 수있을 정도로 충분히 복잡한 논리 컨버드 모드에서. 가장 일반적으로 직렬화 가능한 모드는 다음과 같습니다 거래가 여러 연속을 실행할 때 필요합니다 데이터베이스의 동일한보기를보아야하는 명령.

13.2.2.1. 직렬화 가능한 분리 대표적 일련화 가능성

직관적 인 의미 (및 수학적 정의)의"Serializable"실행입니다 성공적으로 커밋 된 두 개의 동시 거래는 그럴 것입니다 이후에 하나의 연속적으로 엄격하게 실행 된 것으로 보입니다 기타 - 먼저 발생하는 것처럼 보였지만 미리 예측할 수 있습니다. 그것을 실현하는 것이 중요합니다 나열된 바람직하지 않은 행동 금지표 13-1IS 진정한 직렬화 가능성을 보장하기에 충분하지 않으며 실제로PostgreSQL's 직렬화 가능 방법보장하지 않습니다 이러한 의미에서 일련의 실행. 예를 들어, 테이블 고려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는 Sum 330을 계산했을 것입니다. 300, 그리고 마찬가지로 다른 명령은 A에 의해 계산 된 다른 합계

진정한 수학적 직렬화 가능성을 보장하기 위해 데이터베이스 시스템이 시행하는 데 필요합니다술어 잠금트랜잭션은 일치여기서a 다른 동시 거래에서 쿼리. 예를 들어, 한 번 트랜잭션 A가 쿼리를 실행했습니다선택 ... 여기서 클래스 = 1, a 술어 잠금 시스템은 트랜잭션 B를 금지합니다 A가 커밋 될 때까지 클래스 1에 새 행을 삽입합니다.[1]잠금 시스템은 구현하기에 복잡하고 극도로 복잡합니다 모든 세션은 모든 동시에 실행 된 모든 쿼리의 세부 사항 거래. 그리고이 많은 비용은 그 이후로 대부분 낭비됩니다 실제로 대부분의 응용 프로그램은 일종의 일을하지 않습니다. 문제가 발생할 수 있습니다. (확실히 위의 예 오히려 진실하고 실제 소프트웨어를 대표 할 가능성은 거의 없습니다.) 이러한 이유로PostgreSQL술어를 구현하지 않습니다 잠금.

비 서리 화가 불가능한 경우 실행은 진정한 위험이며 문제를 예방할 수 있습니다. 명시 적 잠금의 적절한 사용. 추가 토론 다음 섹션에 나타납니다.

노트

[1]

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