데이터 동시성 및 일관성
이 페이지의 스크립트 콘텐츠는 탐색 용도로만 사용되며 어떤 방식으로든 콘텐츠를 변경하지 않습니다.
이 장에서는 Oracle AI Database가 다중 사용자 데이터베이스 환경에서 일관된 데이터를 유지하는 방법에 대해 설명합니다.
-
데이터 동시성 및 일관성 소개 단일 사용자 데이터베이스에서 사용자는 동일한 데이터를 동시에 수정하는 다른 사용자의 걱정 없이 데이터를 수정할 수 있습니다. 그러나 다중 유저 데이터베이스에서 다중 동시 트랜잭션 내의 명령문은 동일한 데이터를 갱신할 수 있습니다. 동시에 실행하는 트랜잭션은 의미 있고 일관된 결과를 생성해야 합니다.
-
Oracle AI Database Transaction Isolation Levels 개요 트랜잭션 격리 레벨에 대한 ANSI 표준은 각 격리 레벨에 대해 허용되거나 금지되는 현상에 따라 정의됩니다.
-
Oracle AI Database 잠금 방식 개요 잠금은 파괴적인 상호 작용을 방지하는 방식입니다.
-
자동 잠금 개요 Oracle AI Database는 다른 트랜잭션이 동일한 리소스에 대한 배타적 액세스가 필요한 작업을 수행하지 못하도록 트랜잭션 대신 리소스를 자동으로 잠급니다.
-
수동 데이터 잠금 개요 Oracle AI Database 기본 잠금 방식을 수동으로 대체할 수 있습니다.
-
사용자 정의 잠금 개요 Oracle AI Database Lock Management 서비스를 사용하여 특정 애플리케이션에 대한 고유 잠금을 정의할 수 있습니다.
데이터 동시성 및 일관성 소개
단일 유저 데이터베이스에서 유저는 동일한 데이터를 동시에 수정하는 다른 유저의 관심 없이 데이터를 수정할 수 있습니다. 그러나 다중 유저 데이터베이스에서 다중 동시 트랜잭션 내의 명령문은 동일한 데이터를 갱신할 수 있습니다. 동시에 실행하는 트랜잭션은 의미 있고 일관된 결과를 생성해야 합니다.
다중 유저 데이터베이스는 다음을 제공해야 합니다.
-
사용자가 동시에 데이터에 액세스할 수 있도록 보장(데이터 동시성)
-
사용자 고유의 트랜잭션 및 다른 사용자의 커밋된 트랜잭션에 의해 표시되는 변경 사항을 포함하여 각 사용자가 일관된 데이터 뷰(데이터 일관성)를 볼 수 있도록 보장합니다.
트랜잭션이 동시에 실행될 때 일관된 트랜잭션 동작을 설명하기 위해 데이터베이스 연구원은 직렬화 가능성이라는 트랜잭션 격리 모델을 정의했습니다. 직렬화 가능한 트랜잭션은 다른 유저가 데이터베이스에서 데이터를 수정하지 않은 것처럼 보이도록 하는 환경에서 작동합니다.
일반적으로 이러한 트랜잭션 간 격리 정도는 바람직하지만 직렬화 가능한 모드에서 많은 응용 프로그램을 실행하면 응용 프로그램 처리량이 심각하게 손상될 수 있습니다. 동시에 실행되는 트랜잭션을 완전히 격리하면 한 트랜잭션이 다른 트랜잭션에 의해 query되는 테이블에 삽입을 수행할 수 없게 됩니다. 간단히 말해 실제 고려 사항은 일반적으로 완벽한 트랜잭션 격리 및 성능 사이의 절충이 필요합니다.
Oracle AI Database는 다중 버전 일관성 모델과 다양한 유형의 잠금 및 트랜잭션을 사용하여 데이터 일관성을 유지합니다. 이러한 방식으로 데이터베이스는 여러 동시 유저에게 데이터 뷰를 표시할 수 있으며 각 뷰는 특정 시점에 일관됩니다. 여러 버전의 데이터 블록이 동시에 존재할 수 있으므로 트랜잭션은 질의에 필요한 시점에 커밋된 데이터의 버전을 읽고 단일 시점으로 일관된 결과를 반환할 수 있습니다.
-
다중 버전 읽기 일관성 Oracle AI Database에서 다중 버전화는 여러 버전의 데이터를 동시에 구체화하는 기능입니다. Oracle AI Database는 다중 버전 읽기 일관성을 유지합니다.
-
잠금 방식 일반적으로 다중 사용자 데이터베이스는 데이터 잠금의 일부 형식을 사용하여 데이터 동시성, 일관성 및 무결성과 관련된 문제를 해결합니다.
-
ANSI/ISO 트랜잭션 격리 수준 ANSI 및 ISO/IEC에서 채택한 SQL 표준은 4가지 레벨의 트랜잭션 격리를 정의합니다. 이러한 수준은 트랜잭션 처리 능력에 미치는 영향의 정도가 다릅니다. 참조: "데이터 무결성" 및 "거래"
다중 버전 읽기 일관성
Oracle AI Database의 멀티버전은 여러 버전의 데이터를 동시에 구체화할 수 있는 기능입니다. Oracle AI Database는 다중 버전 읽기 일관성을 유지합니다.
Oracle 데이터베이스 질의는 다음과 같은 특성을 갖습니다.
-
읽기 일관성 Query
query에 의해 반환된 데이터는 커밋되어 단일 Point-in-time에 대해 일관성이 있습니다.
주: Oracle AI Database는 더티 읽기를 허용하지 않습니다. 이는 트랜잭션이 다른 트랜잭션에서 커밋되지 않은 데이터를 읽을 때 발생합니다.
더티 읽기의 문제를 설명하기 위해 한 트랜잭션이 커밋하지 않고 열 값을 갱신한다고 가정합니다. 두번째 트랜잭션은 갱신된 값과 커밋되지 않은 값(더티 값)을 읽습니다. 첫번째 세션은 열이 이전 값을 가지도록 트랜잭션을 롤백하지만 두번째 트랜잭션은 갱신된 값을 사용하여 데이터베이스를 훼손합니다. 더티 읽기는 데이터 무결성을 손상시키고 외래 키를 위반하며 고유 제약 조건을 무시합니다.
-
비차단 질의
데이터 읽기 장치와 기록자는 서로 차단하지 않습니다.
-
명령문 레벨 읽기 일관성 Oracle AI Database는 항상 명령문 레벨 읽기 일관성을 시행합니다. 이를 통해 단일 쿼리에서 반환된 데이터가 커밋되고 단일 시점의 일관성을 유지할 수 있습니다.
-
트랜잭션 수준 읽기 일관성 Oracle AI Database는 트랜잭션의 모든 쿼리(트랜잭션 수준 읽기 일관성이라고 함)에 읽기 일관성을 제공할 수도 있습니다.
-
Consistency and Undo Segments 읽기 다중 버전 읽기 일관성 모델을 관리하려면 테이블이 동시에 query 및 갱신될 때 데이터베이스가 읽기 일관성 있는 데이터 집합을 생성해야 합니다.
-
Read Consistency and Deferred Inserts 지연된 삽입이라는 특수한 유형의 삽입은 표준 읽기 일관성 방식을 사용하지 않습니다. 참조: "잠금 동작 요약"
명령문 레벨 읽기 일관성
Oracle AI Database는 항상 명령문 레벨 읽기 일관성을 적용합니다. 이를 통해 단일 쿼리에서 반환된 데이터가 커밋되고 단일 시점까지 일관성을 유지할 수 있습니다.
단일 SQL 문의 일관성이 있는 시점은 트랜잭션 격리 수준 및 질의 특성에 따라 달라집니다.
-
읽기 커밋된 격리 레벨에서 이 시점은 명령문이 열린 시간입니다. 예를 들어,
SELECT문이 SCN 1000에서 열리면 이 명령문은 SCN 1000과 일치합니다. -
직렬화 가능 또는 읽기 전용 트랜잭션에서 이 시점은 트랜잭션이 시작된 시간입니다. 예를 들어, 트랜잭션이 SCN 1000에서 시작되고 이 트랜잭션에서 여러
SELECT문이 발생하는 경우 각 명령문은 SCN 1000과 일치합니다. -
Flashback Query 작업(
SELECT ... AS OF)에서SELECT문은 해당 시점을 명시적으로 지정합니다. 예를 들어, 지난 목요일 오후 2시에 나타난 대로 테이블을 query할 수 있습니다.
참조: Flashback Query에 대한 자세한 내용은 Oracle AI Database Development Guide를 참조하십시오.
트랜잭션 레벨 읽기 일관성
또한 Oracle AI Database는 트랜잭션 내 모든 쿼리(트랜잭션 레벨 읽기 일관성이라고도 함)에 읽기 일관성을 제공할 수 있습니다.
이 경우 트랜잭션의 각 명령문은 동일한 시점의 데이터를 볼 수 있습니다. 트랜잭션이 시작된 시간입니다.
직렬화 가능한 트랜잭션에 의해 수행된 Query는 트랜잭션 자체에 의해 수행된 변경 사항을 확인합니다. 예를 들어, employees를 업데이트한 다음 employees를 질의하는 트랜잭션에 업데이트가 표시됩니다. 트랜잭션 레벨 읽기 일관성은 반복 가능한 읽기를 생성하며 phantom reads에 질의를 노출하지 않습니다.
읽기 일관성 및 언두 세그먼트
다중 버전 읽기 일관성 모델을 관리하려면 테이블이 동시에 query 및 갱신될 때 데이터베이스가 읽기 일관성 있는 데이터 집합을 생성해야 합니다.
Oracle AI Database는 언두 데이터를 통해 읽기 일관성을 달성합니다.
유저가 데이터를 수정할 때마다 Oracle AI Database는 언두 항목을 생성하여 언두 세그먼트에 기록합니다. 언두 세그먼트에는 커밋되지 않은 트랜잭션 또는 최근에 커밋된 트랜잭션에 의해 변경된 이전 데이터 값이 포함됩니다. 따라서 서로 다른 Point-in-time에 있는 동일한 데이터의 여러 버전이 데이터베이스에 존재할 수 있습니다. 데이터베이스는 서로 다른 시점의 데이터 스냅샷을 사용하여 데이터에 대한 읽기 일관성 뷰를 제공하고 비블록화 query를 활성화할 수 있습니다.
읽기 일관성은 단일 인스턴스 및 Oracle RAC(Oracle Real Application Clusters) 환경에서 보장됩니다. Oracle RAC는 캐시 결합이라는 캐시 간 블록 전송 메커니즘을 사용하여 데이터베이스 Instance 간에 데이터 블록의 읽기 일관성 이미지를 전송합니다.
-
읽기 일관성: 예제 이 예제에서는 언두 데이터를 사용하여 읽기 커밋된 격리 레벨에서 명령문 레벨 읽기 일관성을 제공하는 질의를 보여줍니다.
-
읽기 일관성 및 관심 있는 트랜잭션 목록 모든 세그먼트 블록의 블록 헤더에는 관심 있는 트랜잭션 목록(ITL)이 포함됩니다.
참조:
-
"실행 취소 세그먼트" - 실행 취소 스토리지에 대해 알아보기
-
LOB에 대한 읽기 일관성 메커니즘에 대해 알아보려면 Oracle AI Database SecureFiles and Large Objects Developer's Guide를 참조하십시오.
읽기 일관성: 예제
이 예제에서는 언두 데이터를 사용하여 읽기 커밋된 격리 레벨에서 명령문 레벨 읽기 일관성을 제공하는 질의를 보여줍니다.
그림 1: 읽기 커밋된 격리 수준의 읽기 일관성

데이터베이스가 query 대신 데이터 블록을 검색할 때 데이터베이스는 query가 시작될 때 각 블록의 데이터가 블록의 내용을 반영하도록 합니다. 데이터베이스는 필요에 따라 변경 사항을 블록으로 롤백하여 query 처리가 시작된 시점으로 블록을 재구성합니다.
데이터베이스는 트랜잭션 순서를 보장하기 위해 SCN이라는 내부 순서 지정 방식을 사용합니다. SELECT 문이 실행 단계에 들어감에 따라 데이터베이스는 질의 실행이 시작된 시점에 기록된 SCN을 결정합니다. 그림 12-1에서 이 SCN은 10023입니다. Query에는 SCN 10023과 관련된 커밋된 데이터만 표시됩니다.
그림 12-1에서 SCN이 10023 이후에 있는 블록은 SCN이 10024인 두 블록에 표시된 대로 변경된 데이터를 나타냅니다. SELECT 문에는 커밋된 변경 사항과 일치하는 블록 버전이 필요합니다. 데이터베이스는 현재 데이터 블록을 새 버퍼에 복사하고 언두 데이터를 적용하여 이전 버전의 블록을 재구성합니다. 이러한 재구성된 데이터 블록을 CR(일관성 읽기) 복제본이라고 합니다.
그림 12-1에서 데이터베이스는 두 개의 CR 복제(clone)를 생성합니다. 한 블록은 SCN 10006에 일관되고 다른 블록은 SCN 10021에 일관됩니다. 데이터베이스는 질의에 대해 재구성된 데이터를 반환합니다. 이러한 방식으로 Oracle AI Database는 더티 읽기를 방지합니다.
참조: "데이터베이스 버퍼 캐시" 및 "시스템 변경 번호(SCN)"
일관성 및 관심 있는 트랜잭션 목록 읽기
모든 세그먼트 블록의 블록 헤더에는 관심 있는 트랜잭션 목록(ITL)이 포함됩니다.
데이터베이스는 ITL을 사용하여 데이터베이스가 블록을 수정하기 시작할 때 트랜잭션이 커밋되지 않았는지 확인합니다.
ITL의 항목은 행이 잠겨 있는 트랜잭션과 커밋된 변경 사항과 커밋되지 않은 변경 사항이 포함된 블록의 행을 설명합니다. ITL은 언두 세그먼트의 트랜잭션 테이블을 가리키며 이 테이블은 데이터베이스의 변경 시기에 대한 정보를 제공합니다.
어떤 의미에서는 블록 헤더가 블록의 각 행에 영향을 준 최근 트랜잭션 기록을 포함합니다. CREATE TABLE 및 ALTER TABLE 문의 INITRANS 매개변수는 유지되는 트랜잭션 기록의 양을 제어합니다.
참조: Oracle AI Database SQL Language Reference에서 INITRANS 매개변수에 대해 알아보기
읽기 일관성 및 지연된 삽입
지연된 삽입이라는 특수 유형의 삽입은 표준 읽기 일관성 방식을 사용하지 않습니다.
지연된 삽입은 MEMOPTIMIZE_WRITE 힌트를 사용하여 MEMOPTIMIZE FOR WRITE로 지정된 테이블에 삽입합니다. 데이터베이스는 이러한 삽입을 버퍼 캐시가 아닌 Large Pool에 버퍼링합니다. 데이터베이스는 리두 및 언두를 사용하여 변경 사항을 추적하지 않습니다. 대신, SMCO(Space Management Coordinator)가 버퍼를 디스크에 기록할 때 데이터베이스는 변경 사항을 자동으로 커밋합니다. 변경 사항을 롤백할 수 없습니다.
지연 삽입은 다음과 같은 중요한 방법으로 일반 삽입과 다릅니다.
-
응용 프로그램이 커밋한 것으로 간주하는 대용량 풀에 있는 데이터는 손실될 수 있습니다. 예를 들어, 응용 프로그램에서 변경 사항이 저장되었다고 보고하더라도 변경 사항이 디스크에 저장되기 전에 데이터베이스 Instance가 실패할 수 있습니다.
-
메모리에서 직접 데이터를 읽는 것은 허용되지 않습니다. 작성기는 백그라운드 프로세스가 변경 사항을 디스크에 기록하기 전까지는 자체 변경 사항을 읽을 수 없습니다. 커밋된 변경 사항이 디스크에 기록될 때까지는 어떤 읽기 장치도 볼 수 없습니다.
데이터 손실을 방지해야 하는 클라이언트 응용 프로그램은 대용량 풀에 기록한 후 데이터의 로컬 복사본을 유지해야 합니다. 클라이언트는 DBMS_MEMOPTIMIZE 패키지를 사용하여 메모리에 대한 쓰기 지속성을 추적하고, 데이터베이스가 디스크에 강제로 쓰도록 DBMS_MEMOPTIMIZE_ADMIN 패키지를 사용할 수 있습니다.
참조:
-
MEMOPTIMIZE FOR WRITE힌트에 대한 자세한 내용은 Oracle AI Database SQL Language Reference를 참조하십시오.
잠금 방식
일반적으로 다중 유저 데이터베이스는 데이터 동시성, 일관성 및 무결성과 관련된 문제를 해결하기 위해 일부 형태의 데이터 잠금을 사용합니다.
잠금은 동일한 리소스에 액세스하는 트랜잭션 간의 파괴적인 상호 작용을 방지하는 방식입니다.
참조: "Oracle AI Database Locking Mechanism 개요"
ANSI/ISO 트랜잭션 격리 수준
ANSI와 ISO/IEC에서 모두 채택한 SQL 표준은 네 가지 레벨의 트랜잭션 격리를 정의합니다. 이러한 수준은 트랜잭션 처리 능력에 미치는 영향의 정도가 다릅니다.
이러한 격리 수준은 동시에 실행되는 트랜잭션 간에 방지되어야 하는 현상에 따라 정의됩니다. 예방 가능한 현상은 다음과 같습니다.
-
더티 읽기
트랜잭션은 아직 커밋되지 않은 다른 트랜잭션에 의해 기록된 데이터를 읽습니다
-
반복 불가능(퍼지) 읽기
트랜잭션은 이전에 읽은 데이터를 다시 읽고 커밋된 다른 트랜잭션이 데이터를 수정하거나 삭제했음을 확인합니다. 예를 들어, 유저가 행을 query한 다음 나중에 동일한 행을 query하여 데이터가 변경되었음을 발견하면 됩니다.
-
팬텀 읽기
트랜잭션은 검색 조건을 충족하는 행 집합을 반환하는 query를 재실행하여 해당 조건을 충족하는 다른 커밋된 트랜잭션이 추가 행을 삽입했음을 확인합니다.
예를 들어, 트랜잭션은 사원 수를 query합니다. 5분 후 동일한 query를 수행하지만 다른 유저가 새 채용에 대한 레코드를 삽입했기 때문에 이 숫자가 증가했습니다. 더 많은 데이터가 이전보다 조회 기준을 충족하지만 퍼지 읽기와 달리 이전에 읽은 데이터는 변경되지 않습니다.
SQL 표준은 특정 격리 수준에서 실행되는 트랜잭션이 경험할 수 있는 현상 측면에서 4가지 수준의 격리를 정의합니다. 표 12-1은 레벨을 보여줍니다.
표 1 격리 수준별 예방 가능한 읽기 현상
| 분리 레벨 | 더티 읽기 | 반복 불가능 읽기 | 팬텀 읽기 |
|---|---|---|---|
| 커밋되지 않음 읽기 | 가능 | 가능 | 가능 |
| 커밋된 항목 읽기 | 불가능함 | 가능 | 가능 |
| 반복 가능한 검침 | 불가능함 | 불가능함 | 가능 |
| 직렬화 가능 | 불가능함 | 불가능함 | 불가능함 |
Oracle AI Database는 읽기 커밋(기본값) 및 직렬화 가능한 격리 수준을 제공합니다. 또한 데이터베이스는 읽기 전용 모드를 제공합니다.
참조:
-
읽기 커밋, 직렬화 및 읽기 전용 격리 레벨에 대해 알아보려면 "Oracle AI Database Transaction Isolation Levels 개요"를 참조하십시오.
-
Oracle AI Database의 SQL 표준 준수에 대한 논의를 위한 Oracle AI Database SQL Language Reference
Oracle AI Database 트랜잭션 격리 수준 개요
트랜잭션 격리 레벨에 대한 ANSI 표준은 각 격리 레벨에 대해 허용되거나 금지되는 현상에 따라 정의됩니다.
Oracle AI Database는 다음과 같은 트랜잭션 격리 수준을 제공합니다.
-
커밋된 격리 수준 읽기 읽기 커밋된 격리 수준에서 트랜잭션에 의해 실행된 모든 쿼리는 트랜잭션이 아닌 쿼리 전에 커밋된 데이터만 볼 수 있습니다.
-
일련화 가능한 격리 수준 일련화 가능한 격리 수준에서 트랜잭션은 쿼리가 아닌 트랜잭션이 시작될 때 커밋된 변경 사항과 트랜잭션 자체의 변경 사항만 볼 수 있습니다.
-
읽기 전용 격리 수준 읽기 전용 격리 수준은 직렬화 가능한 격리 수준과 유사하지만 읽기 전용 트랜잭션은 사용자가
SYS이 아닌 경우 트랜잭션에서 데이터를 수정할 수 있도록 허용하지 않습니다.
참조:
-
트랜잭션 격리 수준에 대해 자세히 알아보려면 Oracle AI Database Development Guide를 참조하십시오.
-
SET TRANSACTION ISOLATION LEVEL에 대한 자세한 내용은 Oracle AI Database SQL Language Reference 및 Oracle AI Database PL/SQL Language Reference를 참조하십시오.
커밋된 격리 수준 읽기
읽기 커밋된 격리 수준에서 트랜잭션에 의해 실행되는 모든 쿼리는 트랜잭션 시작이 아닌 쿼리 전에 커밋된 데이터만 볼 수 있습니다.
이 격리 수준이 기본값입니다. 충돌 가능성이 적은 트랜잭션이 있는 데이터베이스 환경에 적합합니다.
읽기 커밋된 트랜잭션의 query는 query가 진행되는 동안 커밋되는 데이터를 읽지 않도록 합니다. 예를 들어, query가 백만 행 테이블의 스캔을 통해 중간 정도이고 다른 트랜잭션이 행 950,000에 대한 갱신을 커밋하는 경우 query는 행 950,000을 읽을 때 이러한 변경 사항을 볼 수 없습니다. 그러나 데이터베이스에서 다른 트랜잭션이 질의에서 읽은 데이터를 수정할 수 없으므로 다른 트랜잭션은 질의 실행 사이 데이터를 변경할 수 있습니다. 따라서 동일한 query를 두 번 실행하는 트랜잭션에 퍼지 읽기 및 팬텀이 발생할 수 있습니다.
-
읽기 커밋된 격리 레벨의 읽기 일관성 데이터베이스는 모든 질의에 대해 일관된 결과 집합을 제공하여 사용자가 아무 작업도 수행하지 않고 데이터 일관성을 보장합니다.
-
읽기 커밋된 트랜잭션의 충돌 쓰기 읽기 커밋된 트랜잭션에서 충돌하는 쓰기는 트랜잭션이 커밋되지 않은 동시 트랜잭션에 의해 업데이트된 행을 변경하려고 시도할 때 발생합니다.
읽기 커밋된 격리 레벨의 읽기 일관성
데이터베이스는 모든 query에 대해 일관된 결과 집합을 제공하므로 유저가 아무 작업도 수행하지 않고 데이터 일관성을 보장합니다.
UPDATE 문에서 WHERE 절에 의해 암시된 질의와 같은 암시적 질의는 일관된 결과 집합을 보장합니다. 그러나 암시적 질의의 각 명령문은 DML 문 자체에 의해 수행된 변경 사항을 볼 수 없지만 변경되기 전에 존재했던 데이터를 볼 수 있습니다.
SELECT 목록에 PL/SQL 함수가 포함된 경우 데이터베이스는 상위 SQL 레벨이 아닌 PL/SQL 함수 코드 내에서 SQL 실행을 위한 명령문 레벨에서 명령문 레벨 읽기 일관성을 적용합니다. 예를 들어, 함수는 다른 유저가 데이터를 변경하고 커밋한 테이블에 액세스할 수 있습니다. 함수에서 SELECT를 실행할 때마다 새 읽기 일관성 스냅샷이 설정됩니다.
참조: "하위 질의"
읽기 커밋된 트랜잭션에서 충돌하는 쓰기
읽기 커밋된 트랜잭션에서 충돌하는 쓰기는 트랜잭션이 커밋되지 않은 동시 트랜잭션에 의해 갱신된 행을 변경하려고 할 때 발생합니다.
행 수정을 방지하는 트랜잭션을 차단 트랜잭션이라고도 합니다. 읽기 커밋된 트랜잭션은 차단 중인 트랜잭션이 해당 행 잠금을 종료하고 해제할 때까지 대기합니다.
옵션은 다음과 같습니다.
-
차단 중인 트랜잭션이 롤백되면 대기 중인 트랜잭션은 다른 트랜잭션이 존재하지 않는 것처럼 이전에 잠긴 행을 변경합니다.
-
차단 중인 트랜잭션이 커밋되어 잠금을 해제할 경우 대기 중인 트랜잭션은 새로 변경된 행에 대한 의도된 갱신 작업을 계속합니다.
다음 표에서는 직렬화 가능 또는 읽기 커밋이 가능한 트랜잭션 1이 읽기 커밋된 트랜잭션 2와 상호 작용하는 방식을 보여줍니다. 손실 업데이트라는 일반적인 상황을 보여줍니다. 트랜잭션 1이 수행한 업데이트는 트랜잭션 1이 커밋한 경우에도 테이블에 없습니다. 손실된 업데이트를 처리하기 위한 전략을 고안하는 것은 애플리케이션 개발의 중요한 부분입니다.
표 2 READ COMMITTED 트랜잭션에서 충돌하는 쓰기 및 손실된 업데이트
| 세션 1 | 세션 2 | 설명 |
|---|---|---|
SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6200
Greene 9500 |
작업이 없습니다. | 세션 1은 Banda, Greene 및 Hintz에 대한 급여를 질의합니다. Hintz라는 사원을 찾을 수 없습니다. |
SQL> UPDATE employees SET salary = 7000 WHERE last_name = 'Banda'; |
작업이 없습니다. | 세션 1은 Banda 급여를 갱신하여 트랜잭션을 시작합니다. 트랜잭션 1의 기본 격리 수준은 READ COMMITTED입니다. |
| 작업이 없습니다. | SQL> SET TRANSACTION ISOLATION LEVEL READ COMMITTED; |
세션 2는 트랜잭션 2를 시작하고 격리 수준을 명시적으로 READ COMMITTED로 설정합니다. |
| 작업이 없습니다. | SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6200
Greene 9500 |
트랜잭션 2는 Banda, Greene 및 Hintz의 급여를 질의합니다. Oracle AI Database는 읽기 일관성을 사용하여 트랜잭션 1의 커밋되지 않은 업데이트 전에 Banda의 급여를 표시합니다. |
| 작업이 없습니다. | SQL> UPDATE employees SET salary = 9900 WHERE last_name='Greene'; |
트랜잭션 1이 Banda 행만 잠겼으므로 트랜잭션 2가 Greene에 대한 임금을 성공적으로 업데이트합니다. |
SQL> INSERT INTO employees (employee_id, last_name, email, hire_date, job_id) VALUES (210, 'Hintz', 'JHINTZ', SYSDATE, 'SH_CLERK'); |
작업이 없습니다. | 트랜잭션 1은 사원 Hintz에 대한 행을 삽입하지만 커밋하지 않습니다. |
| 작업이 없습니다. | SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6200
Greene 9900 |
트랜잭션 2는 사원 Banda, Greene 및 Hintz에 대한 급여를 질의합니다. 트랜잭션 2에는 Greene의 급여에 대한 자체 갱신 사항이 표시됩니다. 트랜잭션 2에는 Banda의 급여에 대한 커밋되지 않은 갱신 또는 트랜잭션 1에서 만든 Hintz에 대한 삽입이 표시되지 않습니다. |
| 작업이 없습니다. | SQL> UPDATE employees SET salary = 6300 WHERE last_name = 'Banda'; -- prompt does not return |
트랜잭션 2가 트랜잭션 1에 의해 현재 잠겨 있는 Banda의 행을 업데이트하려고 시도하여 충돌하는 쓰기를 생성합니다. 트랜잭션 2는 트랜잭션 1이 종료될 때까지 대기합니다. |
SQL> COMMIT; |
작업이 없습니다. | 트랜잭션 1은 작업을 커밋하고 트랜잭션을 종료합니다. |
| 작업이 없습니다. | 1 row updated. SQL> |
이제 Banda 행에 대한 잠금이 해제되므로 트랜잭션 2가 Banda의 급여를 계속 업데이트합니다. |
| 작업이 없습니다. | SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6300
Greene 9900
Hintz |
트랜잭션 2는 사원 Banda, Greene 및 Hintz에 대한 급여를 질의합니다. 이제 트랜잭션 1에서 커밋한 힌츠 삽입은 트랜잭션 2에서 볼 수 있습니다. 트랜잭션 2에는 Banda 급여에 대한 자체 업데이트가 표시됩니다. |
| 작업이 없습니다. | COMMIT; |
트랜잭션 2는 작업을 커밋하고 트랜잭션을 종료합니다. |
SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6300
Greene 9900
Hintz |
작업이 없습니다. | 세션 1은 Banda, Greene 및 Hintz에 대한 행을 쿼리합니다. Banda의 급여는 트랜잭션 2에 의해 갱신되는 6300입니다. Banda의 급여를 거래 1에 의해 만들어진 7000으로 업데이트하면 이제 "손실"됩니다. |
참조:
-
손실된 업데이트에 대해 알아보려면 "잠금 사용"을 누르십시오.
-
"Row Locks (TX)"를 사용하여 데이터베이스에서 행 잠금을 획득하는 시기와 이유를 알아봅니다.
직렬화 가능 격리 수준
직렬화 가능한 격리 레벨에서 트랜잭션은 질의 시작이 아닌 트랜잭션 시 커밋된 변경 사항 및 트랜잭션 자체에 의한 변경 사항만 봅니다.
직렬화 가능한 트랜잭션은 다른 유저가 데이터베이스에서 데이터를 수정하지 않은 것처럼 보이도록 하는 환경에서 작동합니다. 직렬화 가능한 격리는 환경에 적합합니다.
-
큰 데이터베이스와 소수의 행만 갱신하는 짧은 트랜잭션 사용
-
두 개의 동시 트랜잭션이 동일한 행을 수정할 확률이 상대적으로 낮은 경우
-
상대적으로 장기 실행 트랜잭션이 주로 읽기 전용인 경우
직렬화가 가능한 격리에서는 일반적으로 명령문 레벨에서 얻은 읽기 일관성이 전체 트랜잭션으로 확장됩니다. 트랜잭션에서 읽은 모든 행은 다시 읽을 때 동일하게 보장됩니다. 모든 query는 트랜잭션 기간 동안 동일한 결과를 반환하도록 보장되므로 다른 트랜잭션에 의해 수행된 변경 사항은 실행된 시간에 관계없이 query에 표시되지 않습니다. 직렬화 가능한 트랜잭션에는 더티 읽기, 퍼지 읽기 또는 팬텀 읽기가 발생하지 않습니다.
Oracle AI Database는 직렬화 가능한 트랜잭션이 시작될 때 다른 트랜잭션이 수행한 행에 대한 변경사항이 이미 커밋된 경우에만 직렬화 가능한 트랜잭션이 행을 수정할 수 있도록 허용합니다. 직렬화 가능한 트랜잭션이 직렬화 가능한 트랜잭션이 시작된 후 커밋된 다른 트랜잭션에 의해 변경된 데이터를 업데이트 또는 삭제하려고 시도할 때 데이터베이스는 오류를 생성합니다.
ORA-08177: Cannot serialize access for this transaction
ORA-08177 오류로 인해 직렬화 가능한 트랜잭션이 실패하면 응용 프로그램이 다음을 비롯한 여러 작업을 수행할 수 있습니다.
-
해당 시점까지 실행된 작업 커밋
-
트랜잭션에서 이전에 설정된 저장점으로 롤백한 후 다른 추가 명령문을 실행합니다.
-
전체 트랜잭션을 롤백합니다
다음 표에서는 직렬화 가능한 트랜잭션이 다른 트랜잭션과 상호 작용하는 방식을 보여줍니다. 직렬화 가능한 트랜잭션이 직렬화 가능한 트랜잭션이 시작된 후 다른 트랜잭션에서 커밋한 행을 변경하지 않으면 직렬화된 액세스 문제가 방지됩니다.
테이블 3 일련번호 지정가능 트랜잭션
| 세션 1 | 세션 2 | 설명 |
|---|---|---|
|
작업이 없습니다. | 세션 1은 Banda, Greene 및 Hintz에 대한 급여를 질의합니다. Hintz라는 사원을 찾을 수 없습니다. |
|
작업이 없습니다. | 세션 1은 Banda 급여를 갱신하여 트랜잭션 1을 시작합니다. 기본 격리 수준은 READ COMMITTED입니다. |
| 작업이 없습니다. | |
세션 2는 트랜잭션 2를 시작하고 SERIALIZABLE 격리 수준으로 설정합니다. |
| 작업이 없습니다. | |
트랜잭션 2는 Banda, Greene 및 Hintz의 급여를 질의합니다. Oracle AI Database는 읽기 일관성을 사용하여 트랜잭션 1에서 수행한 커밋되지 않은 업데이트 이전 Banda의 급여를 표시합니다. |
| 작업이 없습니다. | |
Banda 행만 잠겨 있으므로 트랜잭션 2에서 Greene 급여를 성공적으로 업데이트합니다. |
|
작업이 없습니다. | 트랜잭션 1은 사원 힌트에 대한 행을 삽입합니다. |
|
작업이 없습니다. | 트랜잭션 1은 작업을 커밋하고 트랜잭션을 종료합니다. |
|
|
세션 1은 사원 Banda, Greene 및 Hintz에 대한 급여를 질의하고 트랜잭션 1에서 커밋한 변경 사항을 확인합니다. 세션 1에는 트랜잭션 2에서 수행한 커밋되지 않은 Greene 갱신이 표시되지 않습니다. 트랜잭션 2는 사원 Banda, Greene 및 Hintz에 대한 급여를 질의합니다. Oracle AI Database 읽기 일관성을 통해 트랜잭션 1에서 커밋한 Hintz 삽입 및 Banda 업데이트가 트랜잭션 2에 표시되지 않습니다. 트랜잭션 2에서는 Greene 급여에 대한 자체 갱신 내용을 확인합니다. |
| 작업이 없습니다. | |
트랜잭션 2는 작업을 커밋하고 트랜잭션을 종료합니다. |
|
|
두 세션 모두 Banda, Greene 및 Hintz의 급여를 query합니다. 각 세션은 트랜잭션 1과 트랜잭션 2에 의해 커밋된 모든 변경 사항을 봅니다. |
|
작업이 없습니다. | 세션 1은 Hintz 급여를 갱신하여 트랜잭션 3을 시작합니다. 트랜잭션 3의 기본 격리 수준은 READ COMMITTED입니다. |
| 작업이 없습니다. | |
세션 2는 트랜잭션 4를 시작하고 SERIALIZABLE 격리 수준으로 설정합니다. |
| 작업이 없습니다. | |
트랜잭션 4가 Hintz에 대한 급여 업데이트를 시도하지만 트랜잭션 3이 Hintz 행을 잠갔기 때문에 트랜잭션 4가 차단되었습니다. 트랜잭션 3 뒤의 트랜잭션 4 대기열입니다. |
|
작업이 없습니다. | 트랜잭션 3은 Hintz 급여 갱신을 커밋하고 트랜잭션을 종료합니다. |
| 작업이 없습니다. | |
트랜잭션 3을 종료하는 커밋으로 인해 트랜잭션 4의 Hintz 업데이트가 ORA-08177 오류와 함께 실패합니다. 트랜잭션 3이 트랜잭션 4가 시작된 후에 힌트 업데이트를 커밋했기 때문에 문제 오류가 발생합니다. |
| 작업이 없습니다. | |
세션 2는 트랜잭션을 종료하는 트랜잭션 4를 롤백합니다. |
| 작업이 없습니다. | |
세션 2는 트랜잭션 5를 시작하고 SERIALIZABLE 격리 수준으로 설정합니다. |
| 작업이 없습니다. | |
트랜잭션 5는 Banda, Greene 및 Hintz의 급여를 질의합니다. 트랜잭션 3에서 커밋한 Hintz 급여 갱신이 표시됩니다. |
| 작업이 없습니다. | |
트랜잭션 5는 힌츠 급여를 다른 값으로 갱신합니다. 트랜잭션 3의 Hintz 업데이트는 트랜잭션 5가 시작되기 전에 커밋되었으므로 직렬화된 액세스 문제를 피합니다. 참고: 트랜잭션 5가 시작된 후 다른 트랜잭션이 Hintz 행을 업데이트하고 커밋한 경우 직렬화된 액세스 문제가 다시 발생합니다. |
| 작업이 없습니다. | |
세션 2는 문제 없이 갱신을 커밋하고 트랜잭션을 종료합니다. |
참조:
-
"행 잠금(TX)"
읽기 전용 격리 수준
읽기 전용 격리 레벨은 직렬화 가능한 격리 레벨과 비슷하지만, 사용자가 SYS이 아니면 읽기 전용 트랜잭션에서 데이터를 수정할 수 없습니다.
읽기 전용 트랜잭션은 ORA-08177 오류에 취약하지 않습니다. 읽기 전용 트랜잭션은 트랜잭션이 시작된 시간과 관련하여 내용이 일치해야 하는 보고서를 생성하는 데 유용합니다.
Oracle AI Database는 언두 세그먼트에서 필요에 따라 데이터를 재구성하여 읽기 일관성을 제공합니다. 언두 세그먼트는 순환 방식으로 사용되므로 데이터베이스가 언두 데이터를 겹쳐쓸 수 있습니다. 장기 실행 보고서는 읽기 일관성에 필요한 언두 데이터가 다른 트랜잭션에서 재사용되었을 수 있으므로 snapshot too old 오류가 발생할 위험이 있습니다. 실행 취소 보존 기간(데이터베이스가 이전 실행 취소 데이터를 덮어쓰기 전에 보존하려고 시도하는 최소 시간)을 적절하게 설정하면 이 문제가 방지됩니다.
참조:
-
Oracle AI Database Administrator's Guide에서 언두 보존 기간을 설정하는 방법 알아보기
Oracle AI Database 잠금 방식 개요
잠금은 파괴적인 상호 작용을 방지하는 메커니즘입니다.
상호 작용은 공유 데이터에 액세스하는 트랜잭션 간에 데이터를 잘못 업데이트하거나 기본 데이터 구조를 잘못 변경하는 경우 파괴적입니다. 잠금은 데이터베이스 동시성과 일관성을 유지 관리하는 데 중요한 역할을 합니다.
-
잠금 동작 요약 데이터베이스는 잠금을 획득한 작업에 따라 여러 가지 유형의 잠금을 유지 관리합니다.
-
잠금 사용 단일 사용자 데이터베이스에서는 한 사용자만 정보를 수정하므로 잠금이 필요하지 않습니다. 그러나 여러 유저가 데이터에 액세스하고 데이터를 수정하는 경우 데이터베이스는 동일한 데이터가 동시에 수정되지 않도록 해야 합니다.
-
잠금 모드 Oracle AI Database는 자동으로 적용 가능한 최하위 레벨을 사용하여 데이터 동시성에 대한 최상위 정도를 제공하지만 안전한 데이터 무결성도 제공합니다.
-
잠금 변환 및 에스컬레이션 Oracle AI Database는 필요에 따라 잠금 변환을 수행합니다.
-
잠금 기간 Oracle AI Database는 특정 이벤트가 발생할 때 자동으로 잠금을 해제하므로 트랜잭션에 더 이상 리소스가 필요하지 않습니다.
-
잠금 및 교착 상태 교착 상태는 두 명 이상의 사용자가 서로 잠긴 데이터를 대기하고 있는 상황입니다. 교착 상태는 일부 트랜잭션이 계속 작동하지 않도록 합니다.
잠금 동작 요약
데이터베이스는 잠금을 획득한 작업에 따라 서로 다른 여러 유형의 잠금을 유지 관리합니다.
일반적으로 데이터베이스는 배타적 잠금과 공유 잠금이라는 두 가지 유형의 잠금을 사용합니다. 행이나 테이블과 같은 자원에서는 하나의 배타적 잠금만 얻을 수 있지만 하나의 자원에서는 많은 공유 잠금을 얻을 수 있습니다.
잠금은 읽기 장치와 기록자의 상호 작용에 영향을 줍니다. 리더는 리소스에 대한 질의인 반면, 작성기는 리소스를 수정하는 명령문입니다. 다음 규칙은 읽기 장치 및 쓰기 장치용 Oracle AI Database의 잠금 동작을 요약합니다.
-
기록자에 의해 수정된 경우에만 행이 잠깁니다.
명령문이 한 행을 갱신하면 트랜잭션이 이 행에 대해서만 Lock을 획득합니다. 데이터베이스는 행 레벨에서 테이블 데이터를 Lock하여 동일한 데이터의 경합을 최소화합니다. 일반적인 상황에서각주 1 데이터베이스는 행 잠금을 블록 또는 테이블 레벨로 에스컬레이트하지 않습니다.
-
행 기록자는 동일한 행의 동시 기록자를 차단합니다.
한 트랜잭션이 행을 수정하는 경우 행 잠금은 다른 트랜잭션이 동일한 행을 동시에 수정하지 못하도록 합니다.
-
독자는 결코 작가를 차단하지 않습니다.
행의 판독기는 행을 잠그지 않으므로 작성기는 이 행을 수정할 수 있습니다. 유일한 예외는
SELECT ... FOR UPDATE문입니다. 이 문은 읽고 있는 행을 잠그는 특수 유형의SELECT문입니다. -
작가는 독자를 차단하지 않습니다.
기록자에 의해 행이 변경되는 경우 데이터베이스는 언두 데이터를 사용하여 기록자에게 일관성 있는 행 뷰를 제공합니다.
주: 보류 중인 분산 트랜잭션의 특수한 경우 데이터 판독기는 동일한 데이터 블록의 작성자를 기다려야 할 수 있습니다.
참조:
-
SELECT ... FOR UPDATE에 대한 자세한 내용은 Oracle AI Database SQL Language Reference를 참조하십시오. -
Oracle AI Database Administrator's Guide - 의심스러운 분산 트랜잭션과 연관된 대기에 대해 알아보기
잠금 사용
단일 유저 데이터베이스에서는 한 유저만 정보를 수정하기 때문에 Lock이 필요하지 않습니다. 그러나 여러 유저가 데이터에 액세스하고 데이터를 수정하는 경우 데이터베이스는 동일한 데이터가 동시에 수정되지 않도록 해야 합니다.
Lock은 다음과 같은 중요한 데이터베이스 요구 사항을 충족합니다.
-
일관성
세션에서 보거나 변경 중인 데이터는 유저가 완료하기 전까지 다른 세션에서 변경해서는 안됩니다.
-
무결성
데이터와 구조는 모든 변경 사항을 올바른 순서로 반영해야 합니다.
Oracle AI Database는 잠금 메커니즘을 통해 트랜잭션 간에 데이터 동시성, 일관성 및 무결성을 제공합니다. 잠금은 자동으로 수행되며 사용자 작업이 필요하지 않습니다.
잠금의 필요성은 단일 행의 동시 갱신으로 나타낼 수 있습니다. 다음 예제에서 간단한 웹 기반 응용 프로그램은 일반 유저에게 사원 전자 메일 및 전화 번호를 제공합니다. 응용 프로그램은 다음과 같은 UPDATE 문을 사용하여 데이터를 수정합니다.
UPDATE employees
SET email = ?, phone_number = ?
WHERE employee_id = ?
AND email = ?
AND phone_number = ?
앞의 UPDATE 문에서 WHERE 절의 전자 메일 및 전화 번호 값은 지정된 사원의 수정되지 않은 원래 값입니다. 이 업데이트는 응용 프로그램이 마지막으로 읽고 사용자에게 표시한 후 응용 프로그램에서 수정하는 행이 변경되지 않았는지 확인합니다. 이러한 방식으로 응용 프로그램은 한 사용자가 다른 사용자의 변경 사항을 덮어쓰는 손실된 업데이트 문제를 방지하여 두번째 사용자의 업데이트를 효과적으로 손실합니다. 표 12-2는 손실된 업데이트의 예를 보여줍니다. 표 12-4는 두 세션이 employees 테이블에서 거의 동시에 동일한 행을 수정하려고 시도할 때의 이벤트 순서를 보여줍니다.
표 4 행 잠금 예제
| T | 세션 1 | 세션 2 | 설명 |
|---|---|---|---|
| t0 | |
세션 1에서 hr1 유저는 Himuro 레코드에 대해 hr.employees를 query하고 employee_id(118), 전자 메일(GHIMURO) 및 전화 번호(515.127.4565) 속성을 표시합니다. |
|
| t1 | |
세션 2에서 hr2 유저는 Himuro 레코드에 대해 hr.employees를 query하고 employee_id(118), 전자 메일(GHIMURO) 및 전화 번호(515.127.4565) 속성을 표시합니다. |
|
| t2 | |
세션 1에서 hr1 사용자는 행의 전화 번호를 515.555.1234로 갱신하여 GHIMURO 행에 대한 잠금을 얻습니다. |
|
| t3 | |
세션 2에서
|
|
| t4 | |
세션 1에서 커밋은 Himuro를 영구적으로 변경하고 대기 중인 세션 2의 블록을 해제합니다. |
|
| t5 | |
세션 2에서 술어가 일치하지 않기 때문에 세션 2는 레코드를 갱신하지 않습니다. |
|
| t6 | |
세션 1에서 hr1 유저는 전화 번호가 잘못되어 GHIMURO 행이 갱신되었음을 알 수 있습니다. 사용자는 새 트랜잭션을 시작하고 행의 전화 번호를 515.555.1235로 갱신하여 GHIMURO 행을 잠급니다. |
|
| t7 | |
세션 2에서 hr2 유저는 Himuro 레코드에 대해 hr.employees를 query합니다. 레코드에는 세션 1(t4)에서 커밋한 전화 번호 업데이트가 표시됩니다. Oracle AI Database 읽기 일관성은 세션 2에 t6에서 수행된 커밋되지 않은 변경 사항이 표시되지 않도록 합니다. |
|
| t8 | |
세션 2에서 hr2 사용자는 동일한 행을 갱신하려고 하지만 hr1가 현재 행을 처리하고 있으므로 차단됩니다. |
|
| t9 | |
세션 1에서 hr1 사용자는 트랜잭션을 롤백하여 종료합니다. |
|
| t10 | |
세션 2에서 세션 1 갱신이 롤백되었으므로 전화 번호 갱신에 성공합니다. GHIMURO 행이 해당 술어와 일치하므로 갱신이 성공합니다. |
|
| t11 | |
세션 2는 갱신을 커밋하고 트랜잭션을 종료합니다. |
Oracle AI Database는 SQL 문을 실행할 때 필요한 잠금을 자동으로 획득합니다. 예를 들어, 데이터베이스에서 세션이 데이터를 수정할 수 있도록 허용하기 전에 먼저 해당 세션이 데이터를 lock해야 합니다. Lock이 해제될 때까지 lock된 데이터를 다른 트랜잭션에서 수정할 수 없도록 lock은 세션에 배타적 데이터 제어를 제공합니다.
Oracle AI Database의 잠금 메커니즘은 트랜잭션 제어와 밀접하게 연관되어 있기 때문에 애플리케이션 디자이너는 트랜잭션을 제대로 정의하기만 하면 Oracle AI Database에서 자동으로 잠금을 관리합니다. Oracle AI Database를 사용하면 사용자가 수동으로 데이터를 잠글 수도 있지만 사용자는 명시적으로 리소스를 잠글 필요가 없습니다.
다음 섹션에서는 Oracle AI Database가 데이터 동시성을 달성하는 방법을 이해하는 데 중요한 개념에 대해 설명합니다.
참조: Oracle AI Database PL/SQL Packages and Types Reference 업데이트 손실을 방지하는 데 도움이 되는 서브 프로그램이 포함된 OWA_OPT_LOCK 패키지에 대해 알아봅니다.
Lock 모드
Oracle AI Database는 자동으로 적용 가능한 최하위 레벨을 사용하여 데이터 동시성에 대한 최상위 정도를 제공하지만 안전한 데이터 무결성도 제공합니다.
레벨이 덜 제한적일수록 다른 사용자가 데이터에 액세스할 수 있습니다. 반대로 레벨이 더 제한적일수록 다른 트랜잭션은 획득할 수 있는 lock 유형에 속합니다.
Oracle AI Database는 다중 사용자 데이터베이스에서 두 가지 잠금 모드를 사용합니다.
-
배타적 잠금 모드
이 모드에서는 연관된 리소스가 공유되지 않습니다. 트랜잭션은 데이터를 수정할 때 배타적 잠금을 가져옵니다. 자원을 배타적으로 잠그는 첫번째 트랜잭션은 배타적 잠금을 해제할 때까지 자원을 변경할 수 있는 유일한 트랜잭션입니다.
-
공유 잠금 모드
이 모드에서는 관련 작업에 따라 연관된 리소스를 공유할 수 있습니다. 데이터를 읽는 여러 사용자가 데이터를 공유할 수 있으며, 각 사용자는 공유 잠금을 보유하여 배타적 잠금이 필요한 작성기의 동시 액세스를 방지할 수 있습니다. 다중 트랜잭션은 동일한 자원에 대한 공유 잠금을 획득할 수 있습니다.
트랜잭션에서 SELECT ... FOR UPDATE 문을 사용하여 단일 테이블 행을 선택한다고 가정합니다. 이 트랜잭션은 배타적 행 잠금을 획득하고 행 공유 테이블 잠금을 획득합니다. 행 잠금을 사용하면 다른 세션에서 잠긴 행이 아닌 모든 행을 수정할 수 있으며 테이블 잠금은 세션에서 테이블의 구조를 변경하는 것을 방지합니다. 따라서 데이터베이스는 가능한 많은 명령문 실행을 허용합니다.
잠금 변환 및 에스컬레이션
Oracle AI Database는 필요에 따라 잠금 변환을 수행합니다.
잠금 변환 시 데이터베이스는 낮은 제한성의 테이블 잠금을 더 높은 제한성 중 하나로 자동으로 변환합니다. 예를 들어, 트랜잭션이 직원에 대해 SELECT ... FOR UPDATE를 발행하고 나중에 잠긴 행을 업데이트한다고 가정합니다. 이 경우 데이터베이스는 행 공유 테이블 잠금을 행 배타적 테이블 잠금으로 자동으로 변환합니다. 트랜잭션은 트랜잭션 내에서 삽입, 갱신 또는 삭제된 모든 행에 대해 배타적 행 잠금을 보유합니다. 행 잠금은 가장 높은 수준의 제한성으로 획득되기 때문에 잠금 변환이 필요하거나 수행되지 않습니다.
잠금 변환은 잠금 에스컬레이션과 다릅니다. 잠금은 한 레벨의 세분성(예: 행)에서 여러 잠금이 유지되고 데이터베이스가 잠금을 더 높은 레벨의 세분성(예: 테이블)으로 올릴 때 발생합니다. 세션이 테이블의 여러 행을 lock하는 경우 일부 데이터베이스는 자동으로 행 lock을 단일 테이블로 escalate합니다. Lock 수는 감소하지만 Lock된 Lock의 제한성은 증가합니다.
Oracle AI Database는 잠금을 에스컬레이션하지 않습니다. Lock escalation은 Deadlock의 가능성을 크게 높입니다. 시스템에서 트랜잭션 1을 대신하여 잠금을 에스컬레이트하려고 하지만 트랜잭션 2가 보유한 잠금 때문에 에스컬레이트할 수 없다고 가정합니다. Deadlock은 트랜잭션 2를 진행하기 전에 동일한 데이터의 lock escalation이 필요한 경우 생성됩니다.
잠금 기간
Oracle AI Database는 특정 이벤트가 발생할 때 자동으로 잠금을 해제하므로 트랜잭션에 더 이상 리소스가 필요하지 않습니다.
일반적으로 데이터베이스는 트랜잭션 기간 동안 트랜잭션 내의 명령문에 의해 획득된 잠금을 보유합니다. 이러한 잠금은 더티 읽기, 손실된 업데이트 및 파괴적인 DDL과 같은 파괴적인 간섭을 동시 트랜잭션에서 방지합니다. 주: 인덱스화되지 않은 외래 키로 인해 하위 테이블에 대해 수행된 테이블 잠금은 트랜잭션이 아닌 명령문 기간 동안 유지됩니다. 또한 DBMS_LOCK 패키지를 사용하면 유저 정의 잠금을 원하는 대로 해제 및 할당하고 트랜잭션 경계를 넘어 보유할 수 있습니다.
Oracle AI Database는 커밋 또는 롤백 시 트랜잭션 내의 명령문에서 획득한 모든 잠금을 해제합니다. 또한 Oracle AI Database는 저장점으로 롤백할 때 저장점 이후에 획득한 잠금을 해제합니다. 그러나 이전에 잠긴 리소스를 대기하지 않는 트랜잭션만 현재 사용 가능한 리소스에 대한 잠금을 획득할 수 있습니다. 대기 중인 트랜잭션은 원래 트랜잭션이 커밋되거나 완전히 롤백될 때까지 계속 기다립니다.
참조:
-
트랜잭션 대기 동작을 보여주는 "표 13-3"
-
DBMS_LOCK에 대한 자세한 내용은 "사용자 정의 잠금 개요"를 참조하십시오.
잠금 및 교착 상태
잠금 해제는 두 명 이상의 사용자가 서로 잠긴 데이터를 대기하는 상황입니다. 교착 상태는 일부 트랜잭션이 계속 작동하지 않도록 합니다.
Oracle AI Database는 교착 상태와 관련된 하나의 명령문을 롤백하여 충돌하는 행 잠금의 한 세트를 해제함으로써 교착 상태를 자동으로 감지하고 이를 해결합니다. 데이터베이스는 명령문 레벨 롤백이 수행되는 트랜잭션에 해당하는 메시지를 반환합니다. 롤백된 명령문은 Deadlock을 감지한 트랜잭션에 속합니다. 일반적으로 신호 처리된 트랜잭션은 명시적으로 롤백되어야 하지만 대기한 후에 롤백된 명령문을 재시도할 수 있습니다. 표 12-5는 교착 상태의 두 트랜잭션을 보여줍니다.
표 5 교착 상태인 트랜잭션
| T | 세션 1 | 세션 2 | 설명 |
|---|---|---|---|
| t0 | |
|
세션 1은 트랜잭션 1을 시작하고 사원 100의 급여를 갱신합니다. 세션 2는 트랜잭션 2를 시작하고 사원 200의 급여를 갱신합니다. 각 트랜잭션은 갱신을 시도하는 행만 잠기므로 문제가 없습니다. |
| t1 | |
|
트랜잭션 1은 현재 트랜잭션 2에 의해 잠긴 사원 200 행을 갱신하려고 합니다. 트랜잭션 2는 현재 트랜잭션 1에 의해 잠긴 사원 100 행을 갱신하려고 합니다. 어떤 트랜잭션도 진행하거나 종료하는 데 필요한 리소스를 확보할 수 없기 때문에 Deadlock이 발생합니다. 각 트랜잭션이 대기하는 시간에 관계없이 충돌하는 Lock이 유지됩니다. |
| t2 | |
트랜잭션 1은 Deadlock을 알리고 t1에서 실행된 주: 교착 상태의 세션 하나만 실제로 교착 상태 오류를 가져오지만 두 세션 중 하나에 오류가 발생할 수 있습니다. |
|
| t3 | |
세션 1은 t0에서 수행한 갱신을 커밋하고 트랜잭션 1을 종료합니다. t1에서 실패한 업데이트가 커밋되지 않았습니다. | |
| t4 | |
트랜잭션 1에 의해 차단되고 있는 트랜잭션 2의 t1에서 업데이트가 실행됩니다. 프롬프트가 반환됩니다. | |
| t5 | |
세션 2는 t0 및 t1에서 수행한 업데이트를 커밋하여 트랜잭션 2를 종료합니다. |
Deadlock은 대개 트랜잭션이 Oracle AI Database의 기본 잠금을 명시적으로 무효화하는 경우에 발생합니다. Oracle AI Database는 잠금을 에스컬레이션하지 않고 질의에 읽기 잠금을 사용하지 않지만, 페이지 레벨이 아닌 행 레벨 잠금을 사용하므로 교착 상태가 자주 발생하지 않습니다.
참조:
-
Oracle AI Database Development Guide - 테이블을 명시적으로 잠글 때 교착 상태를 처리하는 방법
자동 잠금 개요
Oracle AI Database는 다른 트랜잭션이 동일한 리소스에 배타적으로 액세스해야 하는 작업을 수행하지 못하도록 트랜잭션을 대신하여 리소스를 자동으로 잠급니다.
데이터베이스는 수행 중인 리소스 및 작업에 따라 다른 레벨의 제한성으로 다양한 유형의 잠금을 자동으로 획득합니다. 주: 데이터베이스는 단순 읽기를 수행할 때 행을 잠그지 않습니다.
Oracle AI Database 잠금은 다음 표에 표시된 범주로 나뉩니다.
표 6 잠금 범주
| 잠금 | 설명 | 자세히 알아보기 |
|---|---|---|
| DML Lock | 데이터 보호 예를 들어, 테이블은 전체 테이블을 잠그고 행은 선택한 행을 잠급니다. | "DML 잠금" |
| DDL 잠금 | 테이블 및 뷰의 딕셔너리 정의와 같은 스키마 객체의 구조를 보호합니다. | "DDL 잠금" |
| 시스템 잠금 | 데이터 파일과 같은 내부 데이터베이스 구조를 보호합니다. 래치, 상호 배제 및 내부 잠금은 완전히 자동으로 수행됩니다. | "시스템 잠금" |
-
DML 잠금 DML 잠금은 데이터 잠금이라고도 하며 여러 사용자가 동시에 액세스하는 데이터의 무결성을 보장합니다.
-
DDL 잠금 DDL(데이터 딕셔너리) 잠금은 진행 중인 DDL 작업이 객체에 대해 작동하거나 객체를 참조하는 동안 스키마 객체의 정의를 보호합니다.
-
시스템 잠금 Oracle AI Database는 다양한 유형의 시스템 잠금을 사용하여 내부 데이터베이스 및 메모리 구조를 보호합니다. 이러한 메커니즘은 유저가 발생이나 기간을 제어할 수 없기 때문에 유저가 액세스할 수 없습니다.
DML Lock
데이터 잠금이라고도 하는 DML 잠금은 여러 사용자가 동시에 액세스하는 데이터의 무결성을 보장합니다.
예를 들어, DML 잠금은 두 고객이 온라인 장부 판매자로부터 사용 가능한 장부의 마지막 사본을 구매하는 것을 방지합니다. DML 잠금은 동시에 충돌하는 DML 또는 DDL 작업에서 발생하는 파괴적인 간섭을 방지합니다.
DML 문은 자동으로 다음 유형의 잠금을 획득합니다.
다음 섹션에서는 각 잠금 또는 잠금 모드 유형 뒤의 괄호 안의 약어는 Oracle Enterprise Manager의 잠금 모니터(Enterprise Manager)에서 사용되는 약어입니다. Enterprise Manager는 테이블 잠금 모드(예: RS 또는 SRX)를 나타내지 않고 테이블 잠금에 대해 TM을 표시할 수 있습니다.
-
행 잠금(TX) 행 잠금은 TX 잠금이라고도 하며 테이블의 단일 행에 대한 잠금입니다. 트랜잭션은
INSERT,UPDATE,DELETE,MERGE또는SELECT... FORUPDATE문에 의해 수정된 각 행에 대해 행 잠금을 획득합니다. 행 잠금은 트랜잭션이 커밋 또는 롤백될 때까지 존재합니다. -
테이블 잠금(TM) 테이블 잠금(TM 잠금이라고도 함)은 테이블이
INSERT,UPDATE,DELETE,MERGE,SELECT(FOR UPDATE절 포함) 또는LOCK TABLE문에 의해 수정될 때 트랜잭션에 의해 획득됩니다. -
잠금 및 외래 키 Oracle AI Database는 종속 외래 키와 관련하여 상위 키의 동시성 제어를 극대화합니다.
행 잠금(TX)
TX lock이라고도 하는 행 잠금은 테이블의 단일 행에 대한 잠금입니다. 트랜잭션은 INSERT, UPDATE, DELETE, MERGE 또는 SELECT ... FOR UPDATE 문에 의해 수정된 각 행에 대해 행 잠금을 획득합니다. 행 잠금은 트랜잭션이 커밋 또는 롤백될 때까지 존재합니다.
행 잠금은 주로 두 트랜잭션이 동일한 행을 수정하지 못하도록 하는 대기열 처리 메커니즘의 역할을 합니다. 데이터베이스는 항상 배타적 모드로 수정된 행을 잠그므로 해당 잠금을 보유하고 있는 트랜잭션이 커밋되거나 롤백될 때까지 다른 트랜잭션에서 행을 수정할 수 없습니다. 행 잠금은 가능한 한 가장 미세한 단위 잠금을 제공하므로 가능한 최상의 동시성과 처리 능력을 제공합니다.
주: 데이터베이스 인스턴스 실패로 인해 트랜잭션이 종료되면 블록 레벨 복구는 전체 트랜잭션이 복구되기 전에 행을 사용할 수 있도록 합니다.
트랜잭션이 행에 대한 잠금을 획득하면 해당 트랜잭션은 행을 포함하는 테이블에 대한 잠금도 획득합니다. 테이블 잠금을 사용하면 현재 트랜잭션의 데이터 변경 사항을 재정의하는 충돌하는 DDL 작업을 막을 수 있습니다. 그림 12-2에서는 테이블의 세번째 행에 대한 업데이트를 보여줍니다. Oracle AI Database는 업데이트된 행에 대한 배타적 잠금과 테이블에 대한 배타적 잠금을 자동으로 배치합니다.
그림 2: 행 및 테이블 잠금

-
행 잠금 및 동시성 이 시나리오는 Oracle AI Database가 동시성을 위해 행 잠금을 사용하는 방법을 보여줍니다.
-
행 잠금 저장 잠금 관리자를 사용하여 메모리의 잠금 목록을 유지 관리하는 일부 데이터베이스와 달리 Oracle AI Database는 잠긴 행을 포함하는 데이터 블록에 잠금 정보를 저장합니다.
행 잠금 및 동시성
이 시나리오는 Oracle AI Database가 동시성을 위해 행 잠금을 사용하는 방법을 보여줍니다.
세 개의 세션이 동일한 행을 동시에 query합니다. 세션 1과 2는 계속해서 다른 행에 대해 커밋되지 않은 갱신을 수행하고 세션 3은 갱신하지 않습니다. 각 세션에는 커밋되지 않은 자체 갱신이 표시되지만 다른 세션의 커밋되지 않은 갱신은 표시되지 않습니다.
테이블 7 데이터 동시성 예제
| T | 세션 1 | 세션 2 | 세션 3 | 설명 |
|---|---|---|---|---|
| t0 | |
|
|
세 개의 서로 다른 세션이 사원 100과 101의 ID와 급여를 동시에 query합니다. 각 query에서 반환된 결과는 동일합니다. |
| t1 | |
세션 1은 사원 100의 급여를 갱신하지만 커밋하지 않습니다. 갱신 시 기록자는 갱신된 행에 대해서만 행 레벨 잠금을 획득하므로 다른 기록자가 이 행을 수정할 수 없습니다. | ||
| t2 | |
|
|
각 세션은 동시에 원본 query를 실행합니다. 세션 1은 t1 갱신으로 인한 급여 612를 보여줍니다. 세션 2와 3의 읽기 장치는 행을 즉시 반환하고 세션 1이 트랜잭션을 종료할 때까지 기다리지 않습니다. 데이터베이스는 다중 버전 읽기 일관성을 사용하여 세션 1에서 갱신되기 전의 급여를 표시합니다. |
| t3 | |
세션 2는 사원 101의 급여를 갱신하지만 트랜잭션을 커밋하지 않습니다. 갱신 시 기록자는 갱신된 행에 대해서만 행 레벨 잠금을 획득하므로 다른 기록자가 이 행을 수정할 수 없습니다. | ||
| t4 | |
|
|
각 세션은 동시에 원본 query를 실행합니다. 세션 1은 t1 갱신으로 인한 급여 612를 표시하지만 세션 2에서 수행된 사원 101의 급여 갱신은 표시하지 않습니다. 세션 2의 Reader는 세션 2에서 갱신한 급여를 표시하지만 세션 1에서 갱신한 급여는 표시하지 않습니다. 세션 3의 읽기 장치는 읽기 일관성을 사용하여 세션 1 및 2에 의해 수정되기 전에 급여를 표시합니다. |
참조:
-
V$LOCK에 대한 자세한 내용은 Oracle AI Database Reference를 참조하십시오.
행 잠금 저장 영역
잠금 관리자를 사용하여 메모리의 잠금 목록을 유지 관리하는 일부 데이터베이스와 달리 Oracle AI Database는 잠긴 행을 포함하는 데이터 블록에 잠금 정보를 저장합니다.
데이터베이스는 행 Lock을 획득하기 위해 큐 대기 방식을 사용합니다. 트랜잭션이 잠금 해제된 행에 대해 lock을 요구하는 경우 해당 트랜잭션은 데이터 블록에 lock을 둡니다. 이 트랜잭션에 의해 수정된 각 행은 블록 헤더에 저장된 트랜잭션 ID의 복사본을 가리킵니다.
트랜잭션이 종료되면 트랜잭션 ID는 블록 헤더에 남아 있습니다. 다른 트랜잭션에서 행을 수정하려는 경우 트랜잭션 ID를 사용하여 Lock이 활성 상태인지 확인합니다. Lock이 활성화되어 있으면 Lock이 해제될 때 세션에 알려달라는 메시지가 표시됩니다. 그렇지 않으면 트랜잭션이 lock을 획득합니다.
참조:
-
데이터 블록 헤더에 대해 자세히 알아보려면 "데이터 블록 개요"를 참조하십시오.
-
V$TRANSACTION에 대한 자세한 내용은 Oracle AI Database Reference를 참조하십시오.
테이블 Lock(TM)
테이블 잠금(TM 잠금이라고도 함)은 테이블이 INSERT, UPDATE, DELETE, MERGE, SELECT 및 FOR UPDATE 절 또는 LOCK TABLE 문에 의해 수정될 때 트랜잭션에 의해 획득됩니다.
DML 작업에서는 트랜잭션 대신 테이블에 대한 DML 액세스를 예약하고 트랜잭션과 충돌하는 DDL 작업을 방지하기 위해 테이블 잠금이 필요합니다.
테이블 잠금은 다음 모드에서 보유할 수 있습니다.
-
공유 행(Row Share)(RS)
하위 공유 테이블 잠금(SS)이라고도 하는 이 잠금은 테이블에 대한 잠금을 보유하는 트랜잭션이 테이블의 잠긴 행을 포함하며 해당 행을 업데이트하려고 함을 나타냅니다. 행 공유 잠금은 테이블에 대해 가장 높은 수준의 동시성을 제공하는 테이블 잠금의 가장 제한적인 모드입니다.
-
배타적 행 테이블 잠금(Row Exclusive Table Lock, RX)
제외 테이블 잠금(SX)이라고도 하는 이 잠금은 일반적으로 잠금을 보유하는 트랜잭션이 테이블 행을 업데이트했거나
SELECT ... FOR UPDATE를 실행했음을 나타냅니다. SX 잠금을 사용하면 다른 트랜잭션이 동일한 테이블에서 여러 행을 동시에 질의, 삽입, 업데이트, 삭제 또는 잠글 수 있습니다. 따라서 SX 잠금을 사용하면 여러 트랜잭션이 동일한 테이블에 대해 동시에 SX 및 하위 공유 테이블 잠금을 얻을 수 있습니다. -
테이블 잠금 공유(S)
트랜잭션이 보유한 공유 테이블 잠금을 사용하면 다른 트랜잭션이
SELECT ... FOR UPDATE를 사용하지 않고 테이블을 질의할 수 있지만, 단일 트랜잭션이 공유 테이블 잠금을 보유하고 있는 경우에만 갱신이 허용됩니다. 여러 트랜잭션이 공유 테이블 잠금을 동시에 보유할 수 있으므로 이 잠금을 보유하는 것만으로는 트랜잭션이 테이블을 수정할 수 없습니다. -
배타적 행 공유 테이블 잠금(Share Row Exclusive Table Lock, SRX)
공유 하위 배타적 테이블 잠금(SSX)이라고도 하는 이 잠금은 공유 테이블 잠금보다 더 제한적입니다. 한 번에 하나의 트랜잭션만 주어진 테이블에 대해 SSX 잠금을 획득할 수 있습니다. 트랜잭션이 보유한 SSX 잠금을 사용하면 다른 트랜잭션이
SELECT ... FOR UPDATE를 제외하고 테이블을 질의할 수 있지만 테이블을 갱신할 수는 없습니다. -
배타적 테이블 잠금(X)
이 Lock은 다른 트랜잭션이 임의의 유형의 DML 문을 수행하거나 테이블에 임의의 유형의 lock을 배치하는 것을 금지하는 가장 제한적인 Lock입니다.
참조:
-
테이블 잠금에 대해 자세히 알아보려면 Oracle AI Database Development Guide를 참조하십시오.
잠금 및 외래 키
Oracle AI Database는 종속 외래 키와 관련하여 상위 키의 동시성 제어를 극대화합니다.
잠금 동작은 외래 키 열의 인덱스 여부에 따라 달라집니다. 외래 키가 인덱스화되지 않으면 하위 테이블이 더 자주 잠기고 Deadlock이 발생하여 동시성이 감소합니다. 이러한 이유로 외래 키는 거의 항상 인덱스화되어야 합니다. 유일한 예외는 일치하는 고유 키 또는 기본 키가 업데이트되거나 삭제되지 않는 경우입니다.
-
잠금 및 인덱스화되지 않은 외래 키 하위 테이블의 외래 키 열에 인덱스가 없고 세션이 상위 테이블의 기본 키를 수정하는 경우(예: 행을 삭제하거나 기본 키 속성을 수정하는 경우) 하위 테이블에 대한 전체 테이블 잠금을 획득하거나 행을 상위 테이블로 병합합니다.
-
Locks and Indexed Foreign Keys The database does not acquire a full table lock on the child table when a foreign key column in the child table is indexed, and a session modifies a primary key in the parent table (for example, deletes a row or modifies primary key attributes) or merges rows into the parent table.
잠금 및 인덱스화되지 않은 외래 키
데이터베이스는 하위 테이블의 Foreign Key 열에 대한 인덱스가 없는 경우 하위 테이블에 대해 전체 테이블 잠금을 획득하고, 세션이 상위 테이블의 Primary Key를 수정하거나(예: 행 삭제 또는 Primary Key 속성 수정) 행을 상위 테이블로 병합합니다.
다음 두 조건이 모두 참이면 데이터베이스는 하위 테이블에 대해 전체 테이블 잠금을 획득합니다.
-
하위 테이블의 외래 키 열에 인덱스가 존재하지 않습니다.
-
세션은 상위 테이블의 Primary Key를 수정하거나(예를 들어, 행을 삭제하거나 Primary Key 속성을 수정) 행을 상위 테이블로 병합합니다. 주: 상위 테이블에 삽입하면 하위 테이블에 대한 DML을 방지하는 차단 테이블 잠금을 획득하지 않습니다. 삽입의 경우 데이터베이스는 하위 테이블에 대한 잠금을 획득하여 구조적 변경은 방지하지만 기존 행이나 새로 추가된 행은 수정하지 않습니다.
hr.departments 테이블이 인덱스화되지 않은 외래 키 employees.department_id를 포함하는 hr.employees의 상위라고 가정합니다. 다음 그림은 departments 테이블에서 부서 60의 기본 키 속성을 수정하는 세션을 보여줍니다.
그림 3: 인덱스화되지 않은 외래 키를 사용한 잠금 메커니즘

그림 12-3에서 데이터베이스는 부서 60의 기본 키 수정 중 employees에 대한 전체 테이블 잠금을 획득합니다. 이 잠금을 사용하면 다른 세션에서 employees 테이블을 질의할 수 있지만 갱신할 수는 없습니다. 예를 들어, 세션은 사원 전화 번호를 갱신할 수 없습니다. employees에 대한 테이블 잠금은 departments 테이블에 대한 기본 키 수정이 완료된 직후 해제됩니다. departments의 여러 행에 기본 키 수정이 수행되는 경우 employees에 대한 테이블 잠금을 획득하고 departments에서 수정된 각 행에 대해 한 번 릴리스합니다. 주: 하위 테이블의 DML은 상위 테이블에 대한 테이블 잠금을 획득하지 않습니다.
잠금 및 인덱스화된 외래 키
The database does not acquire a full table lock on the child table when a foreign key column in the child table is indexed, and a session modifies a primary key in the parent table (for example, deletes a row or modifies primary key attributes) or merges rows into the parent table.
상위 테이블에 대한 잠금은 트랜잭션이 배타적 테이블 잠금을 획득하는 것을 방지하지만 기본 키를 수정하는 동안 상위 또는 하위 테이블에 대한 DML을 차단하지 않습니다. 이러한 상황은 하위 테이블에서 갱신이 발생하는 동안 상위 테이블에서 Primary Key 수정이 발생하는 경우에 선호됩니다. 그림 12-4는 인덱스화된 department_id 열이 있는 하위 테이블 employees를 보여줍니다. 트랜잭션은 departments에서 부서 280을 삭제합니다. 이 삭제로 인해 데이터베이스가 "Locks and Unindexed Foreign Keys"에 설명된 시나리오에서와 같이 employees 테이블에 대한 전체 테이블 잠금을 획득하지 않습니다.
그림 4: 색인화된 외래 키를 사용한 잠금 메커니즘

하위 테이블이 ON DELETE CASCADE를 지정하는 경우 상위 테이블에서 삭제하면 하위 테이블에서 삭제될 수 있습니다. 예를 들어 부서 280을 삭제하면 삭제된 부서의 사원에 대해 employees에서 레코드가 삭제될 수 있습니다. 이 경우 대기 및 잠금 규칙은 상위 테이블에서 행을 삭제한 후 하위 테이블에서 행을 삭제한 경우와 동일합니다.
참조:
-
"인덱스 소개"
DDL 잠금
DDL(데이터 딕셔너리) 잠금은 진행 중인 DDL 작업이 객체에 대해 작동하거나 객체를 참조하는 동안 스키마 객체의 정의를 보호합니다.
수정되거나 참조되는 개별 스키마 객체만 DDL 작업 중에 잠깁니다. 데이터베이스는 전체 데이터 딕셔너리를 잠그지 않습니다.
Oracle AI Database는 DDL이 필요한 모든 DDL 트랜잭션 대신 DDL 잠금을 자동으로 획득합니다. 사용자는 DDL 잠금을 명시적으로 요청할 수 없습니다. 예를 들어, 사용자가 저장된 프로시저를 생성하는 경우 Oracle AI Database는 자동으로 프로시저 정의에 참조된 모든 스키마 객체에 대한 DDL 잠금을 획득합니다. DDL 잠금을 사용하면 프로시저 컴파일이 완료되기 전에 이러한 객체가 변경되거나 삭제되지 않습니다.
-
배타적 DDL 잠금 배타적 DDL 잠금은 다른 세션이 DDL 또는 DML 잠금을 획득하지 못하도록 합니다.
-
공유 DDL 잠금 리소스에 대한 공유 DDL 잠금은 충돌하는 DDL 작업과의 파괴적인 간섭을 방지하지만 유사한 DDL 작업에 대한 데이터 동시성을 허용합니다.
-
구문 분석 잠금 구문 분석 잠금은 참조하는 각 스키마 객체에 대해 SQL 문 또는 PL/SQL 프로그램 단위가 보유합니다.
배타적(Exclusive) DDL 잠금
배타적 DDL 잠금은 다른 세션에서 DDL 또는 DML 잠금을 획득하는 것을 막습니다.
대부분의 DDL 작업은 동일한 스키마 객체를 수정하거나 참조하는 다른 DDL 작업과의 파괴적인 간섭을 방지하기 위해 리소스에 대해 배타적 DDL 잠금을 필요로 합니다. 예를 들어, DROP TABLE는 ALTER TABLE가 열을 추가하는 동안 테이블을 삭제할 수 없으며 그 반대의 경우도 마찬가지입니다.
배타적(Exclusive) DDL 잠금은 DDL 문 실행 및 자동 커밋 기간 동안 지속됩니다. 배타적 DDL 잠금을 획득하는 동안 다른 작업이 스키마 객체에 대해 다른 DDL 잠금을 보유하는 경우, 획득은 이전 DDL 잠금이 해제될 때까지 기다린 다음 계속 진행합니다.
참조: "Share DDL Locks"에서는 파괴적 간섭을 방지하기 위해 배타적 잠금이 필요하지 않은 상황에 대해 설명합니다.
DDL 잠금 공유
리소스에 대한 공유 DDL 잠금은 충돌하는 DDL 작업과의 파괴적인 간섭을 막지만, 유사한 DDL 작업에 대한 데이터 동시성을 허용합니다.
예를 들어, CREATE PROCEDURE 문을 실행하면 포함 트랜잭션이 참조되는 모든 테이블에 대해 공유 DDL 잠금을 획득합니다. 다른 트랜잭션은 동일한 테이블을 참조하는 프로시저를 동시에 생성하고 동일한 테이블에 대해 동시 공유 DDL 잠금을 획득할 수 있지만 참조된 테이블에 대해 어떠한 트랜잭션도 배타적 DDL 잠금을 획득할 수 없습니다.
공유 DDL 잠금은 DDL 문 실행 및 자동 커밋 기간 동안 지속됩니다. 따라서 공유 DDL 잠금을 보유한 트랜잭션은 트랜잭션 중에 참조된 스키마 객체의 정의가 일정하게 유지됩니다.
중단 가능한 구문 분석(Breakable Parse) 잠금
구문 분석 잠금은 참조하는 각 스키마 객체에 대해 SQL 문 또는 PL/SQL 프로그램 단위가 보유합니다.
구문 분석 잠금은 참조된 객체가 변경되거나 삭제될 경우 연관된 공유 SQL 영역을 무효화할 수 있도록 획득됩니다. 구문 분석 잠금은 DDL 작업을 허용하지 않으며 충돌하는 DDL 작업을 허용하도록 손상될 수 있기 때문에 구분할 수 있는 구문 분석 잠금이라고 합니다.
구문 분석 잠금은 SQL 문 실행의 구문 분석 단계 중 공유 풀에서 획득됩니다. 해당 명령문에 대한 공유 SQL 영역이 Shared Pool에 남아 있는 한 Lock이 유지됩니다.
참조: "Shared Pool"
시스템 잠금
Oracle AI Database는 다양한 유형의 시스템 잠금을 사용하여 내부 데이터베이스 및 메모리 구조를 보호합니다. 이러한 메커니즘은 유저가 발생이나 기간을 제어할 수 없기 때문에 유저가 액세스할 수 없습니다.
-
래치 래치는 공유 데이터 구조, 객체 및 파일에 대한 다중 사용자 액세스를 조정하는 간단한 하위 레벨 직렬화 방식입니다.
-
상호 배제 객체 상호 배제 객체(상호 배제 객체)는 동시 프로세스에서 액세스할 때 메모리의 객체가 삭제되거나 손상되지 않도록 하는 하위 레벨의 메커니즘입니다. 상호 배제는 래치와 유사하지만 래치는 일반적으로 객체 그룹을 보호하는 반면 상호 배제는 단일 객체를 보호합니다.
-
내부 잠금 내부 잠금은 래치 및 상호 배제보다 더 높은 레벨의 보다 복잡한 방식이며 다양한 용도로 사용됩니다.
래치
래치는 공유 데이터 구조, 객체 및 파일에 대한 다중 사용자 액세스를 조정하는 간단한 하위 레벨 직렬화 방식입니다.
래치는 여러 프로세스에서 액세스하는 경우 공유 메모리 리소스가 손상되지 않도록 보호합니다. 특히 래치는 다음과 같은 상황에서 데이터 구조를 보호합니다.
-
다중 세션에 의한 동시 수정
-
다른 세션에서 수정하는 동안 한 세션에서 읽는 중
-
액세스되는 동안 메모리의 할당 해제(에이징 아웃)
일반적으로 단일 래치는 SGA의 여러 객체를 보호합니다. 예를 들어, DBW 및 LGWR와 같은 백그라운드 프로세스는 공유 풀에서 메모리를 할당하여 데이터 구조를 만듭니다. 이 메모리를 할당하기 위해 이러한 프로세스는 두 프로세스가 Shared Pool을 동시에 검사하거나 수정하지 못하도록 액세스를 직렬화하는 Shared Pool 래치를 사용합니다. 메모리가 할당된 후에는 다른 프로세스에서 구문 분석에 필요한 라이브러리 캐시와 같은 공유 풀 영역에 액세스해야 할 수도 있습니다. 이 경우 프로세스는 전체 Shared Pool이 아니라 라이브러리 캐시만 래치합니다.
행 잠금과 같은 enqueue 래치와 달리 래치는 세션을 큐에 넣는 것을 허용하지 않습니다. 래치를 사용할 수 있게 되면 래치를 요청하는 첫번째 세션이 배타적 액세스를 얻습니다. 래치 회전 현상은 프로세스가 루프에서 래치를 반복적으로 요청할 때 발생하는 반면, 래치 절전은 프로세스가 래치 요청을 갱신하기 전에 CPU를 해제할 때 발생합니다.
일반적으로 Oracle 프로세스는 데이터 구조를 조작하거나 확인하는 동안 매우 짧은 시간 동안 래치를 획득합니다. 예를 들어, 단일 사원의 급여 갱신을 처리하는 동안 데이터베이스는 수천 개의 래치를 획득하고 해제할 수 있습니다. 래치 구현은 특히 프로세스가 래치를 기다리는지 여부와 기간에 따라 운영 체제에 따라 다릅니다.
래치 증가는 동시성 감소를 의미합니다. 예를 들어, 과도한 하드 구문 분석 작업으로 인해 라이브러리 캐시 래치에 대한 경합이 발생합니다. V$LATCH 뷰에는 각 래치가 요청되고 대기된 횟수를 비롯하여 각 래치에 대한 자세한 래치 사용 통계가 포함되어 있습니다.
참조:
-
V$LATCH에 대한 자세한 내용은 Oracle AI Database Reference를 참조하십시오. -
대기 이벤트 통계에 대한 자세한 내용은 Oracle AI Database Performance Tuning Guide를 참조하십시오.
상호 배제
상호 제외 객체(상호 배제 객체)는 동시 프로세스에서 액세스할 때 메모리의 객체가 삭제되거나 손상되지 않도록 방지하는 하위 레벨 메커니즘입니다. 상호 배제는 래치와 유사하지만 래치는 일반적으로 객체 그룹을 보호하는 반면 상호 배제는 단일 객체를 보호합니다.
상호 배제는 다음과 같은 여러 이점을 제공합니다.
-
상호 배제는 경합 가능성을 줄일 수 있습니다.
래치는 여러 객체를 보호하므로 프로세스가 이러한 객체에 동시에 액세스하려고 할 때 병목이 될 수 있습니다. 그룹이 아닌 개별 객체에 대한 액세스를 직렬화하면 상호 배제의 가용성이 향상됩니다.
-
상호 배제는 래치보다 메모리를 적게 소비합니다.
-
공유 모드에서는 상호 배제가 여러 세션에서 동시 참조를 허용합니다.
내부 잠금
내부 잠금은 래치 및 상호 배제보다 더 높은 레벨의 복잡한 메커니즘으로 다양한 용도로 사용됩니다.
데이터베이스는 다음과 같은 유형의 내부 잠금을 사용합니다.
-
딕셔너리 캐시 잠금
이러한 잠금은 매우 짧은 기간이며 항목이 수정 또는 사용되는 동안 딕셔너리 캐시에 있는 항목에 대해 유지됩니다. 따라서 구문 분석 중인 명령문에는 일관성 없는 객체 정의가 표시되지 않습니다. 딕셔너리 캐시 잠금은 공유되거나 배타적일 수 있습니다. 공유 잠금은 구문 분석이 완료될 때 해제되는 반면 배타적 잠금은 DDL 작업이 완료될 때 해제됩니다.
-
파일 및 로그 관리 잠금
이러한 잠금은 다양한 파일을 보호합니다. 예를 들어, 내부 잠금은 한 번에 하나의 프로세스만 변경할 수 있도록 제어 파일을 보호합니다. 또 다른 잠금은 온라인 리두 로그 파일의 사용 및 아카이브를 조정합니다. 여러 Instance가 데이터베이스를 공유 모드로 마운트하거나 한 Instance가 데이터베이스를 배타적 모드로 마운트하도록 데이터 파일이 잠깁니다. 파일 및 로그 잠금은 파일 상태를 나타내므로 이러한 잠금을 오랫동안 보유해야 합니다.
-
테이블스페이스 및 언두 세그먼트 Lock
이러한 Lock은 테이블스페이스 및 언두 세그먼트를 보호합니다. 예를 들어, 데이터베이스에 액세스하는 모든 Instance는 테이블스페이스가 온라인 상태인지 오프라인 상태인지에 대해 동의해야 합니다. 언두 세그먼트는 하나의 데이터베이스 Instance만 세그먼트에 기록할 수 있도록 잠깁니다.
참조: "데이터 딕셔너리 캐시"
수동 데이터 잠금 개요
Oracle AI Database 기본 잠금 방식을 수동으로 대체할 수 있습니다.
Oracle AI Database는 데이터 동시성, 데이터 무결성 및 명령문 레벨 읽기 일관성을 보장하기 위해 자동으로 잠금을 수행합니다. 그러나 기본 잠금 재정의는 다음과 같은 경우에 유용합니다.
-
응용 프로그램에는 트랜잭션 레벨 읽기 일관성 또는 반복 가능한 읽기 작업이 필요합니다.
이 경우 query는 다른 트랜잭션의 변경 사항을 반영하지 않고 트랜잭션 기간 동안 일관성 있는 데이터를 생성해야 합니다. 명시적 잠금, 읽기 전용 트랜잭션, 직렬화 가능한 트랜잭션 또는 기본 잠금을 재정의하여 트랜잭션 레벨 읽기 일관성을 달성할 수 있습니다.
-
응용 프로그램은 트랜잭션이 다른 트랜잭션이 완료될 때까지 기다릴 필요가 없도록 리소스에 대한 배타적 액세스 권한을 가지고 있어야 합니다.
세션 또는 트랜잭션 레벨에서 Oracle AI Database 자동 잠금을 대체할 수 있습니다. 세션 레벨에서 세션은 ALTER SESSION 문을 사용하여 필요한 트랜잭션 격리 수준을 설정할 수 있습니다. 트랜잭션 레벨에서 다음 SQL 문을 포함하는 트랜잭션은 Oracle AI Database 기본 잠금을 대체합니다.
-
SET TRANSACTION ISOLATION LEVEL문 -
LOCK TABLE문(테이블을 잠그거나 뷰와 함께 사용되는 경우 기본 테이블) -
SELECT ... FOR UPDATE문
이전 명령문에서 획득한 잠금은 트랜잭션이 종료된 후 해제되거나 저장점 해제를 위한 롤백이 해제됩니다.
Oracle AI Database 기본 잠금이 모든 레벨에서 무효화되면 데이터베이스 관리자 또는 응용 프로그램 개발자는 대체 잠금 절차가 올바르게 작동하는지 확인해야 합니다. lock 프로시저는 데이터 무결성이 보장되고, 데이터 동시성이 허용되며, deadlock은 불가능하거나 적절하게 처리되어야 합니다.
참조:
-
LOCK TABLE및SELECT에 대한 설명은 Oracle AI Database SQL Language Reference를 참조하십시오. -
테이블을 수동으로 잠그는 방법에 대한 자세한 내용은 Oracle AI Database Development Guide를 참조하십시오.
유저 정의 Lock 개요
Oracle AI Database Lock Management 서비스를 사용하면 특정 애플리케이션에 대한 자체 잠금을 정의할 수 있습니다.
예를 들어, 파일 시스템의 메시지 로그에 대한 액세스를 직렬화하는 잠금을 만들 수 있습니다. 예약된 사용자 잠금은 Oracle AI Database 잠금과 동일하므로 교착 상태 감지를 포함한 모든 Oracle AI Database 잠금 기능이 있습니다. 사용자 잠금은 접두어 UL로 식별되므로 Oracle AI Database 잠금과 충돌하지 않습니다.
Oracle AI Database Lock Management 서비스는 DBMS_LOCK 패키지의 절차를 통해 사용할 수 있습니다. PL/SQL 블록에 다음 명령문을 포함할 수 있습니다.
-
특정 유형의 잠금 요청
-
동일한 프로시저나 다른 Instance의 다른 프로시저에서 인식할 수 있는 고유 이름을 잠금에 부여합니다.
-
잠금 유형 변경
-
잠금 해제
참조:
-
Oracle AI Database Lock Management 서비스에 대한 자세한 내용은 Oracle AI Database Development Guide를 참조하십시오.
-
DBMS_LOCK에 대한 자세한 내용은 Oracle AI Database PL/SQL 패키지 및 유형 참조를 참조하십시오.
각주 범례
각주 1:
분산된 2상 커밋을 처리할 때 데이터베이스는 특수한 상황에서 잠시 동안 읽기 액세스를 방지할 수 있습니다. 특히, 준비 단계와 커밋 단계 사이에 query가 시작되고 커밋 전에 데이터를 읽으려고 시도하면 데이터베이스가 읽기 일관성을 보장하기 위해 행 레벨에서 블록 레벨로 lock을 에스컬레이션할 수 있습니다.