Postgresql 9.3.25 문서화 | ||||
---|---|---|---|---|
토토 커뮤니티 : 문서 : 9.3 : 소개 | 메이저 토토 사이트 : 문서 : 9.3 : 동시성 제어 | 13 장. 동시체 제어 | PostgreSQL : 문서 : 9.3 : 명시 적 윈 토토 |
theSQL표준은 4를 정의합니다 트랜잭션 격리 수준. 가장 엄격한 것은 직렬화 가능하며 단락에서 표준에 의해 정의되는 것은 일련의 직렬화 배트맨 토토 트랜잭션 세트의 동시 실행입니다 한 번에 하나씩 실행하는 것과 동일한 효과를 생성하도록 보장 어떤 순서로. 다른 세 레벨은 측면에서 정의됩니다 동시 사이의 상호 작용으로 인한 현상 각 레벨에서 발생하지 않아야하는 거래. 표준 직렬화 가능의 정의로 인해이 중 어느 것도 그 수준에서 현상이 가능합니다. (이것은 놀라운 일이 아닙니다. 거래의 효과가 한 번에 하나씩 실행되었는데, 어떻게 상호 작용?)
다양한 수준에서 금지되는 현상은 다음과 같습니다.
트랜잭션은 동시에 커밋되지 않은 데이터를 읽습니다 거래.
트랜잭션은 이전에 읽은 데이터를 다시 읽고 찾았습니다. 해당 데이터는 다른 거래에 의해 수정되었습니다 (커밋 된 것은 처음 읽은 이후).
트랜잭션은 쿼리를 다시 실행하여 행 세트를 반환합니다. 검색 조건을 만족시키고 행 세트가 상태를 만족시키는 것이 다른 상태로 인해 변경되었습니다 최근에 커뮤니케이션 거래.
4 개의 트랜잭션 격리 수준과 해당 행동은에 설명되어 있습니다.표 13-1.
표 13-1. 기준SQL거래 격리 수준
격리 레벨 | 더러운 읽기 | 반복 할 수없는 읽기 | Phantom Read |
---|---|---|---|
커밋되지 않은 읽기 | 가능 | 가능 | 가능 |
Committed 읽기 | 불가능 | 가능 | 가능 |
반복 가능한 읽기 | 불가능 | 불가능 | 가능 |
SERIALIZALE | 불가능 | 불가능 | 불가능 |
inPostgreSQL, 당신은 요청할 수 있습니다 네 가지 표준 트랜잭션 격리 수준 중 하나. 하지만 내부적으로 3 개의 별개의 격리 수준 만 있습니다 저지른 레벨, 반복 가능한 읽기 및 직렬화 가능. 레벨을 선택할 때 실제로는 커밋되지 않은 읽기를 선택하십시오 칭찬을 받고 팬텀 리드가 불가능합니다postgresql구현 반복 가능한 읽기, 실제 격리 수준이 더 엄격 할 수 있습니다. 선택한 것보다. 이것은 SQL 표준에 의해 허용됩니다 4 개의 격리 수준은 어떤 현상이 발생하지 않아야하는지 정의합니다. 그들은 어떤 현상이 일어나야하는지 정의하지 않습니다. 그 이유PostgreSQL3 만 제공합니다 격리 수준은 이것이 유일하게 현명한 방법이라는 것입니다. Multiversion 동시성 제어에 대한 표준 격리 수준 건축학. 이용 가능한 격리 수준의 동작은 다음과 같습니다 다음 하위 섹션에 자세히 설명합니다.
거래의 거래 격리 수준을 설정하려면 명령트랜잭션 설정.
중요 :일부PostgreSQL데이터 유형 및 함수는 거래 행동에 관한 특별 규칙. 특히, 시퀀스에 대한 변경 (따라서 열의 카운터 사용 선언Serial)는 즉시 있습니다 다른 모든 거래에 표시되며 변경이 중단 된 거래. 보다섹션 9.16and섹션 8.1.4.
저지른 읽기기본 격리입니다 레벨PostgreSQL. 언제 a 트랜잭션은이 격리 수준, a를 사용합니다.select쿼리 (a업데이트/공유절)에는 쿼리 이전에 커밋 된 데이터 만 볼 수 있습니다 시작했다; 커밋되지 않은 데이터 나 변경이 커지는 것을 보지 못합니다 동시 트랜잭션으로 쿼리 실행 중. 사실상 Aselect쿼리의 스냅 샷이 보입니다 데이터베이스는 즉시 쿼리가 실행되기 시작합니다. 하지만,select이전의 효과가 나타납니다 자체 거래 내에서 실행 된 업데이트는 아직 커밋되지 않았습니다. 또한 두 가지 연속select명령은 다른 데이터를 볼 수 있습니다 다른 거래가 커밋하는 경우 단일 거래 내에 있습니다. 첫 번째 실행 중 변경select.
업데이트, 삭제, 업데이트 선택, 그리고공유 선택명령은 동일select검색 측면에서 대상 행 : 커밋 된 대상 행만 찾을 수 있습니다. 명령 시작 시간의. 그러나 그러한 대상 행에는 가질 수 있습니다 다른 동시에 이미 업데이트 (또는 삭제 또는 잠금) 트랜잭션이 발견 될 때까지. 이 경우, 그럴 것입니다 업데이트는 첫 번째 업데이트 거래가 커밋되기를 기다립니다. 롤백 (아직 진행중인 경우). 첫 번째 업데이트가 굴리는 경우 뒤로, 그 효과가 부정되고 두 번째 업데이트는 원래 발견 된 행을 업데이트하십시오. 첫 번째 경우 업데이트 커밋, 두 번째 업데이트는 첫 번째 업데이트가 삭제했습니다. 그렇지 않으면 적용하려고합니다. 행의 업데이트 버전으로 작동합니다. 검색 조건 명령의 (여기서절) IS 업데이트 된 행의 행이 여전히 일치하는지 확인하기 위해 재평가했습니다. 검색 조건. 그렇다면 두 번째 업데이트는 그와 함께 진행됩니다 업데이트 된 행의 행을 사용하여 작동합니다. 의 경우업데이트 선택and공유 선택, 이것은 업데이트되었음을 의미합니다 잠겨서 클라이언트로 돌아온 행 버전.
위 규칙으로 인해 업데이트가 가능합니다. 일관되지 않은 스냅 샷을 보도록 명령 : 효과를 볼 수 있습니다. 동일한 행에 동시 업데이트 명령이 업데이트이지만 다른 행에 대한 명령의 영향은 보이지 않습니다. 데이터베이스에서. 이 동작은 저지른 모드를 부적합하게 만듭니다 복잡한 검색 조건과 관련된 명령; 그러나 그것은입니다 더 간단한 경우에 적합합니다. 예를 들어, 은행 업데이트를 고려하십시오 다음과 같은 거래와 균형 :
시작; 업데이트 계정 설정 밸런스 = 밸런스 + 100.00 여기서 acctnum = 12345; 업데이트 계정 설정 밸런스 = 밸런스 -100.00 여기서 acctnum = 7534; 저지르다;
그러한 거래가 동시에 잔액을 변경하려고한다면 계정 12345의 두 번째 트랜잭션이 시작되기를 분명히 원합니다. 계정 행의 업데이트 버전으로. 각 명령이기 때문에 미리 정해진 행에만 영향을 미치며 업데이트 된 것을 볼 수 있습니다. 행의 버전은 번거로움을 만들지 않습니다 불일치.
더 복잡한 사용은 바람직하지 않은 결과를 읽을 수 있습니다 커밋 된 모드. 예를 들어, 고려하십시오.삭제18501_18630웹 사이트는 2 열 테이블입니다 와 함께웹 사이트. hits동등한9and10:
시작; 업데이트 웹 사이트 세트 hits = hits + 1; - 다른 세션에서 실행 : hits = 10 인 웹 사이트에서 삭제; 저지르다;
the삭제조차도 영향을 미치지 않습니다 가 있지만웹 사이트. hits = 10행 전후에업데이트. 이것은 발생합니다 업데이트 전 행 값이기 때문에9is 건너 뛰고업데이트완성 및삭제새 행 값 인 잠금을 얻습니다 더 이상10그러나11, 더 이상 기준과 일치하지 않습니다.
read commited mode가 새 새로 각 명령을 시작하기 때문에 그에 대한 모든 트랜잭션이 포함 된 스냅 샷 동일한 거래의 순간, 후속 명령은 어떤 경우에도 커밋 된 동시 거래의 효과. 그만큼 위의 문제점은 A인지 여부입니다.단일명령은 절대적으로 본다 데이터베이스의 일관된보기.
Read Commited에 의해 제공되는 부분 트랜잭션 격리 많은 응용 프로그램에 적합 하며이 모드는 빠르고 빠르고 사용하기 간단합니다. 그러나 모든 경우에 충분하지는 않습니다. 복잡한 쿼리 및 업데이트를 수행하는 응용 프로그램에는 Commited보다 데이터베이스에 대한보다 엄격하게 일관된보기 모드 제공.
the반복 가능한 읽기분리 레벨 거래가 시작되기 전에 저지른 데이터 만 본다. 결코 커밋되지 않은 데이터 나 변경 중에 커밋 된 변경 사항이 나타납니다 동시 거래에 의한 거래 실행. (그러나, 쿼리는 이전 업데이트가 그 내에서 실행 된 효과를 봅니다. 자신의 거래는 아직 커밋되지 않았지만.) 이것은 가 요구하는 것보다 더 강력한 보증SQL이 격리 수준의 표준 및 에 설명 된 모든 현상을 방지합니다.표 13-1. 처럼 위에서 언급하면, 이것은 표준에 의해 구체적으로 허용되며 만 설명합니다최소각 격리 각각의 보호 레벨은 제공해야합니다.
이 레벨은 쿼리의 쿼리에서 저지른 읽기와 다릅니다. 반복 가능한 읽기 트랜잭션이 시작될 때 스냅 샷을 봅니다.거래트랜잭션 내에서 현재 쿼리의 시작. 따라서, 연속selecta 명령단일거래 참조 동일한 데이터, 즉 다른 사람이 변경 한 변경 사항이 보이지 않습니다. 자신의 거래 후에 저지른 거래 시작.
이 레벨을 사용한 응용 프로그램은 다시 시도해야합니다 직렬화 실패로 인한 거래.
업데이트, 삭제, 업데이트 선택, 그리고공유 선택명령은 동일select검색 측면에서 대상 행 : 커밋 된 대상 행만 찾을 수 있습니다. 거래 시작 시간의. 그러나 그러한 대상 행은 그럴 수 있습니다 다른 사람이 이미 업데이트 (또는 삭제 또는 잠금) 동시 거래가 발견 될 때까지. 이 경우 반복 가능한 읽기 트랜잭션은 첫 번째 업데이트를 기다립니다 커밋 또는 롤백 거래 (아직 진행중인 경우). 만약에 첫 번째 업데이트가 롤백되고 그 효과가 부정되고 반복 가능한 읽기 트랜잭션은 업데이트를 진행할 수 있습니다 원래 Row를 찾았습니다. 그러나 첫 번째 업데이트가 커밋하는 경우 (및 실제로 잠긴 것이 아니라 행을 업데이트하거나 삭제했습니다. 반복 가능한 읽기 트랜잭션은 다시 롤백됩니다 메시지
오류 : 동시 업데이트로 인해 액세스를 직렬화 할 수 없습니다
반복 가능한 읽기 트랜잭션은 행을 수정하거나 잠글 수 없기 때문에 반복 가능한 읽기 트랜잭션 후 다른 거래에 의해 변경되었습니다 시작했다.
응용 프로그램 이이 오류 메시지를 받으면 중단해야합니다. 현재 거래와 전체 거래를 다시 시도합니다. 시작. 두 번째로, 거래는 다음을 볼 것입니다 초기 관점의 일부로 이전에 커밋 된 변화 데이터베이스이므로 새 버전 사용에 대한 논리적 충돌이 없습니다. 새로운 트랜잭션의 출발점으로 행 업데이트.
거래 만 업데이트하는 것만 재조정해야 할 수도 있습니다. 읽기 전용 거래는 직렬화 충돌이 없습니다.
반복 가능한 읽기 모드는 각각 트랜잭션은 데이터베이스의 완전히 안정적인 관점을 본다. 하지만, 이 견해는 반드시 항상 일부와 일치하는 것은 아닙니다. 일련의 (한 번에 하나씩) 동시 거래의 실행 같은 레벨. 예를 들어,이 수준에서 읽기 전용 거래조차도 배치가 완료되었지만not하나를 참조하십시오 배치의 논리적 인 일부인 세부 레코드 중 제어 레코드의 이전 개정판을 읽습니다. 시도 이 격리에서 실행되는 거래로 비즈니스 규칙을 시행합니다 레벨은 신중하게 사용하지 않고는 올바르게 작동하지 않을 것입니다. 충돌하는 거래를 차단하기위한 명시 적 잠금.
참고 :이전PostgreSQL버전 9.1, 요청 요청 직렬화 가능한 트랜잭션 격리 수준은 정확히 동일하게 제공되었습니다 여기에 설명 된 행동. 레거시 직렬화 가능성을 유지합니다 행동, 반복 가능한 읽기가 이제 요청되어야합니다.
theSERIALIZABLE분리 레벨 가장 엄격한 트랜잭션 격리를 제공합니다. 이 레벨은 에뮬레이션됩니다 모든 커밋 된 거래에 대한 직렬 거래 실행; 마치 마치 거래는 연속적으로, 오히려 연속적으로 실행되었습니다 동시에. 그러나 반복 가능한 읽기 레벨과 마찬가지로 이 레벨을 사용하는 응용 프로그램은 다시 시도해야합니다 직렬화 실패로 인한 거래. 사실,이 격리 레벨은 반복 가능한 읽기와 정확히 동일하게 작동합니다. 동시를 실행할 수있는 조건에 대한 모니터링 일련의 일련의 거래는 일관성이없는 방식으로 행동합니다 가능한 모든 일련 (한 번에 하나씩)의 실행으로 업무. 이 모니터링에는 차단이 발생하지 않습니다 그 외에도 반복 가능한 읽기가 있지만 약간의 오버 헤드가 있습니다. 모니터링 및 조건 감지에 원인 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 잠금 장치를 해제 할 수 있습니다. 완료, 충돌이 여전히 발생할 수 없음을 감지하면 직렬화 이상으로 이어질 수 있습니다. 사실은,읽기 전용거래는 종종 가능합니다 스타트 업에서 그 사실을 확립하고 술어 복용을 피하십시오 자물쇠. 명시 적으로 요청하면직렬화 가능 연기 만 읽기트랜잭션은 가능할 때까지 차단됩니다 이 사실을 확립하십시오. (이것은입니다.전용직렬화 가능한 경우 트랜잭션은 차단하지만 반복 가능한 읽기 트랜잭션은 그렇지 않습니다.) 반면에, siread 자물쇠는 종종 거래를 지나야합니다. 겹칠 때까지 거래가 완료 될 때까지 커밋.
직렬화 가능한 트랜잭션의 일관된 사용은 단순화 될 수 있습니다 개발. 모든 세트가 성공적으로 커밋되었다는 보장 동시 직렬화 가능한 트랜잭션은 동일한 영향을 미칩니다 그들이 한 번에 하나씩 달리면 당신이 시연 할 수 있음을 의미합니다. 서면으로 단일 거래가 그 자체로 달리면, 당신은 그것이 옳은 일을 할 것이라는 확신을 가질 수 있습니다. 직렬화 가능한 거래의 혼합에서, 아무 것도없이 다른 거래가 무엇을 할 수 있는지에 대한 정보 또는 성공적으로 커밋되지 않습니다. 환경이 중요합니다 이 기술을 사용하는 일반화 된 처리 방법이 있습니다. 직렬화 실패 (항상 sqlstate 값으로 반환됩니다 '40001'의) 거래는 읽기/쓰기 종속성에 기여할 수 있습니다 직렬화 이상을 방지하려면 롤백해야합니다. 그만큼 읽기/쓰기 종속성의 모니터링은 비용이 있습니다. 직렬화로 종료 된 거래의 재시작 실패, 그러나 사용과 관련된 비용과 차단에 대한 균형 명백한 자물쇠와업데이트 선택또는공유 선택, 직렬화 가능 거래는 일부에게 최고의 성능 선택입니다 환경.
whilePostgreSQL'S 직렬화 가능 트랜잭션 격리 수준은 동시 거래 만 허용합니다 일련의 실행 순서가 있음을 증명할 수 있다면 동일한 효과를 생성하면 항상 오류를 방지하지는 않습니다. 진정한 일련의 실행에서는 발생하지 않을 것입니다. ~ 안에 특히 고유 한 제약 위반을 볼 수 있습니다 시리얼링 가능한 트랜잭션이 중첩되는 것과 충돌하여 발생합니다 키가 이전에 존재하지 않는지 명시 적으로 확인한 후 삽입하려고 시도합니다. 이것은를 확인함으로써 피할 수 있습니다all직렬화 가능 잠재적으로 충돌하는 키를 명시 적으로 삽입하는 트랜잭션 먼저 그렇게 할 수 있는지 확인하십시오. 예를 들어, 응용 프로그램을 상상해보십시오 사용자에게 새 키를 요청한 다음 그렇지 않은지 확인합니다. 먼저 선택하거나 새 키를 생성하여 이미 존재합니다. 최대 기존 키를 선택하고 하나를 추가함으로써. 일부 직렬화 가능한 트랜잭션은 새 키를 직접 삽입하지 않고 직접 삽입하십시오 이 프로토콜에 따라 고유 한 제약 위반이있을 수 있습니다 연재물에서 발생할 수없는 경우에도보고 동시 거래 실행.
직렬화 가능에 의존 할 때 최적의 성능 동시성 통제를위한 거래, 이러한 문제는 이루어져야합니다 존경받는:
거래 선언으로읽기 전용언제 가능한.
연결을 사용하여 활성 연결 수를 제어합니다 필요한 경우 수영장. 이것은 항상 중요한 성능입니다 고려 사항이지만 바쁜 경우 특히 중요 할 수 있습니다. 직렬화 가능한 트랜잭션을 사용하는 시스템.
필요한 것보다 단일 트랜잭션에 더 많이 넣지 마십시오. 무결성 목적.
연결을 방해하지 마십시오"유휴 상태 거래"필요한 것보다 길다.
명시 적 잠금 제거,선택 업데이트및공유 선택어디서 자동으로 제공되는 보호로 인해 더 긴 필요합니다 직렬화 가능한 거래.
시스템이 여러 페이지 레벨을 결합해야 할 때 술어 잠금 장치는 단일 관계 수준의 술어 잠금 장치로 잠금됩니다 술어 잠금 테이블은 메모리가 부족하고 직렬화 실패 속도가 발생할 수 있습니다. 당신은 이것을 피할 수 있습니다 증가max_pred_locks_per_transaction.
순차적 스캔은 항상 관계 수준이 필요합니다 술어 잠금. 이로 인해 비율이 증가 할 수 있습니다 직렬화 실패. 사용을 장려하는 것이 도움이 될 수 있습니다 감소로 인덱스 스캔random_page_cost및/또는 증가CPU_TUPLE_COST. 트랜잭션 롤백 및 재시작의 감소를 계량하십시오. 쿼리 실행 시간의 전반적인 변경에 대해