격리 수준 설명

완료됨

PostgreSQL에는 세 가지 유형의 동시성 충돌인 더티 읽기, 반복 불가능한 읽기, 가상 읽기를 방지하는 두 가지 수준의 트랜잭션 격리가 있습니다.

동시성 제어 유형

더티 읽기

더티 읽기는 한 트랜잭션이 다른 트랜잭션이 편집 중인 업데이트된 버전의 데이터를 읽을 때 발생합니다. 그러나 이 업데이트는 커밋되지 않습니다.

예를 들어, 저축 계좌에서 계좌 잔액을 0 미만으로 만드는 트랜잭션이 발생합니다. 트랜잭션이 커밋되기 전에 계정 잔액을 확인하고 저축 계좌의 잔액이 0보다 작은 것을 허용하지 않으므로 트랜잭션이 롤백됩니다. 동시에 모든 저축 계좌의 현재 잔액을 표시하는 보고서가 실행되고 있습니다. 더티 읽기가 허용되면 커밋되지 않더라도 음수 잔액이 반환됩니다.

반복 불가능한 읽기

반복 불가능한 읽기는 트랜잭션이 데이터를 읽고, 다른 트랜잭션이 데이터를 업데이트하고, 초기 트랜잭션이 데이터를 다시 읽고 새 업데이트를 확인하는 경우에 발생합니다.

예를 들어 연결 A는 트랜잭션을 시작하고 주문의 단위당 비용과 단위 수를 읽습니다. 비용은 10이고 단위 수는 3입니다. 그런 다음, 연결 B는 다른 트랜잭션을 시작하고 동일한 주문을 업데이트하여 단위당 비용을 12로 설정합니다. 원래 쿼리와 동일한 트랜잭션에서 연결 A는 주문의 총 비용을 계산합니다. 반복 불가능한 읽기가 허용되는 경우 연결 A는 단위당 비용이 10이고 단위 수가 3인 총 비용 36을 반환합니다. 이는 분명히 말이 되지 않습니다.

가상 읽기

가상 읽기는 트랜잭션이 데이터를 읽고, 다른 트랜잭션이 데이터에 새 행을 추가하고, 초기 트랜잭션이 데이터를 다시 읽고 새 업데이트를 확인하는 경우 발생합니다.

예를 들어, 연결 A는 트랜잭션을 시작하고 파리에서 그날의 총 청구서 수를 계산합니다. 그 수는 파리의 10개 매장 전체에 대해 총 1,100개의 청구서의 합계였습니다. 그런 다음 연결 B는 또 다른 트랜잭션을 시작하고 새 매장 개장일에 대한 200개의 청구서와 함께 파리에 새 소매점을 추가합니다. 연결 A 트랜잭션에서 시스템은 이제 매장 수를 계산하여 매장당 청구서 수를 계산합니다. 이제 연결 A는 청구서 개수 쿼리를 실행할 때 존재했던 원래 10개가 아닌 11개의 매장으로 1,100개의 트랜잭션을 나눕니다. 연결 A 트랜잭션이 평균 계산에서 고려하지 않은 200개의 청구서가 새 매장에 있었음에도 불구하고 이 계산은 이제 100개의 평균으로 잘못 반환합니다.

격리 수준

Azure Database for PostgreSQL에는 커밋된 읽기, 반복 가능한 읽기, 직렬화 가능한 읽기의 세 가지 트랜잭션 격리 수준이 있습니다. 커밋되지 않은 읽기는 Azure Database for PostgreSQL에서 사용할 수 없습니다.

격리 수준이 동시성 충돌에 미치는 영향:

격리 수준 커밋되지 않은 읽기 반복 불가능한 읽기 가상 읽기
커밋되지 않은 읽기* 가능 가능 가능
커밋된 읽기 가능하지 않음 가능 가능
반복 읽기 가능하지 않음 가능하지 않음 가능
직렬화 가능 가능하지 않음 가능하지 않음 가능하지 않음

* PostgreSQL에서 사용할 수 없음

커밋된 읽기는 Azure Database for PostgreSQL의 기본 격리 수준입니다. 커밋된 읽기는 좋은 성능을 제공하면서 더티 읽기를 방지하므로 대부분의 시나리오에 가장 적합합니다. 반복 불가능 읽기 및 가상 읽기가 가능하지만 이러한 조건은 동일한 데이터를 동시에 쿼리하는 여러 SELECT 문이 있는 경우에만 발생할 수 있습니다.

반복 가능한 읽기는 다른 트랜잭션이 트랜잭션의 두 SELECT 문 실행 사이에 행을 업데이트하더라도 트랜잭션 내의 여러 SELECT 문이 동일한 결과를 볼 수 있으므로 커밋된 읽기와 다릅니다. 다른 트랜잭션이 새 행을 삽입하는 경우 이러한 행은 두 번째 SELECT 문의 결과에 나타나지 않습니다.

직렬화 가능한 격리 수준은 가장 높은 수준의 트랜잭션 격리를 제공하며 서로 다른 트랜잭션이 직렬로, 즉 차례로 실행되는 것처럼 수행됩니다. 직렬화 가능 격리 수준의 단점은 트랜잭션이 업데이트를 수행하는 경우 다른 트랜잭션이 이를 차단할 수 있다는 것입니다. 직렬화 가능 트랜잭션은 차단 트랜잭션이 완료될 때까지 기다려야 하며 이는 성능에 영향을 미칩니다.

직렬화 가능 트랜잭션은 직렬화 가능 트랜잭션 중에 다른 트랜잭션이 수정하는 행을 변경할 수도 없습니다. 이러한 형태의 충돌이 발생하면 오류 메시지가 반환되므로 직렬화 가능한 트랜잭션을 사용할 때 애플리케이션에 다시 시도 논리를 빌드하는 것이 중요합니다.

트랜잭션 격리 수준을 업데이트하려면 트랜잭션 내에서 TRANSACTION ISOLATION LEVEL 명령을 사용합니다.

예시:

BEGIN TRANSACTION
TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM humanresources.department
COMMIT;