프로그래밍/오라클

오라클 성능고도화 원리와 해법 Ⅰ (2장)

나노세컨드 2026. 1. 3. 10:03

트랜잭션과 Lock

DB2, SQL Server, Sybase 등은 Lock을 통해 읽기 일관성을 구현하지만, 오라클은 Undo 데이터를 이용해 읽기 일관성을 구현한다는 게 핵심이다. 즉, Undo에 저장된 정보를 이용해 쿼리가 시작된 시점을 기준으로 일관성 있는 결과집합을 생성해 낸다

 

트랜잭션 동시성 제어

  - 동시성 제어란, 동시에 실행되는 트랜잭션 수를 최대화하면서도 입력, 수정, 삭제, 검색 시 데이터의 무결성이 유지될 수 있도록 노력하는 것을 말한다

  - 동시성 제어가 어려운 이유는 동시성과 일관성이 트레이드 오프 관계에 있다는 데에 있다

  - 트랜잭션의 특징 1) 원자성 2) 일관성 3) 격리성 4) 영속성

 

트랜잭성 수준 읽기 일관성

  - 오라클은 완벽한 문장 수준의 읽기 일관성을 보장하지만, 트랜잭션에 대해서는 기본적으로 보장하지 않는다. 다른 DBMS도 트랜잭션 수준의 읽기 일관성은 보장하지 않는다

  - 트랜잭션 고립화 수준

    1) 레벨 0 (Read Uncommitted) : 트랜잭션 처리 중인, 아직 커밋되지 않은 데이터를 다른 트랜잭션에서 읽는 것을 허용

    2) 레벨 1 (Read Committed) : Dirty Read 방지. 트랜잭션이 커밋되어 확정된 데이터만 읽는 것 허용. 해당 레코드 빠져나가는 순간 Lock 해제

    3) 레벨 2 (Repeatable Read) : 선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때까지 후행 트랜잭션이 갱신하거나 삭제하는 것을 불허함으로써 같은 데이터를 두 번 쿼리 했을 때 일관성 있는 결과 리턴. 오라클은 for update절 이용해 구현가능

    4) 레벨 3 (Serializable) : 완벽한 읽기 일관성 모드를 제공

  - 오라클은 트랜잭션 고립화 수준을 높이더라고 Lock을 사용하지 않으므로 동시성이 저하되지는 않는다

 

비관적 vs 낙관적 동시성 제어

  - 비관적 동시성 제어는 사용자들이 같은 데이터를 동시에 수정할 것이라고 가정한다. 따라서 한 사용자가 데이터를 읽는 시점 Lock을 걸고 조회 또는 갱신처리가 완료될 때까지 이를 유지한다

  - 낙관적 동시성 제어는 사용자들이 같은 데이터를 동시에 수정하지 않을 것이라고 가정한다

 

동시성 구현 사례

  - 일련번호를 채번하고자 할 때 가장 좋은 선택은 DBMS가 제공하는 Sequence 기능을 이용하는 것이다

  - 그 외 방법으로는 1) 데이터가 삽입되는 시점에 실시간으로 현재의 MAX 값을 취해 1만큼 증가 2) MAX 값을 관리하는 채번 테이블에서 가져오는 방식 사용

  - autonomous 트랜잭션  : 오라클은 메인 트랜잭션에 영향을 주지 않고 서브 트랜잭션만 따로 커밋하는 기능

 

오라클 Lock

  - 오라클은 공유 리소스와 사용자 데이터를 보호할 목적으로 DML Lock, DDL Lock, 래치, 버퍼 Lock, 라이브러리 캐시 Lock/Pin 등 다양한 종류의 Lock을 사용한다

  - 라이브러리 캐시 Lock : 라이브러리 캐시 오브젝트에 대한 핸들을 보호

  - 라이브러리 캐시 Pin : 라이브러리 캐시 오브젝트의 실제 내용이 담긴 힙을 보호

  - DML Lock은 다중 사용자에 의해 동시에 액세스 되는 사용자 데이터의 무결성을 보호해 준다. DML Lock에는 테이블 Lock과 로우 Lock이 있다

  - DML 테이블 Lock : Enqueue Lock으로 구현함

  - DML 로우 Lock : 로우 단위 Lock과 트랜잭션 Lock을 조합해서 구현함

  - Enqueue는 공유 리소스에 대한 액세스를 관리하는 Lock 메커니즘. Enqueue Lock은 래치와 달리 순서가 보장되는 큐 구조를 사용한다. 따라서 대기자 큐에 가장 먼저 Lock 요청을 등록한 세션이 가장 먼저 Lock 획득한다

  - 오라클은 Enqueue 리소스 구조체를 통합 관리하는 리소스 테이블을 갖고 있으며, 리소스 테이블에서 관리되는 각 리소스를 찾을 때는 해싱 알고리즘을 사용한다. 물론, 해싱을 위한 해시 키로는 리소스 식별자가 사용된다. 각 해시 버킷에는 연결리스트로 연결된 해시 체인을 가지며, 여기에 리소스 구조체가 연결된다

  - TX Lock : 변경 중인 레코드를 동시에 변경하려는 트랜잭션에 대해서는 액세스를 직렬화해야 하며, 그 목적으로 사용하는 Lock. 트랜잭션이 첫 번째 변경을 시작할 때 얻고, 커밋 또는 롤백할 때 해제한다

  - TX Lock →  무결성 제약 위배 가능성 또는 비트맵 인덱스 엔트리 갱신 : 테이블에 Unique 인덱스가 정의되어 있을 때 insert에 의한 로우 Lock 경합 가능

  - TX Lock → ITL 슬롯 부족 : 동시 트랜잭션 개수가 MAXTRANS 값 초과, PCTFREE를 0으로 지정했거나 PCTFREE 예약 공간을 모두 사용한 상태에서, 새로운 트랜잭션을 위한 ITL 슬록 부족

  - TX Lock → 인덱스 분할 : 값을 입력할 위치에 빈 공간이 없으면 인덱스 분할을 실시해 새 값을 입력할 공간을 확보하게 되며, 이 과정에서 Lock 경합이 발생할 수 있다

  - TX Lock → 기타 트랜잭션 Lock : 읽기 전용 테이블스페이스로 전환할 때도, TX Lock 경합 발생

  - TX Lock → DML 로우 Lock : 로우 Lock은, 두 개의 동시 트랜잭션이 같은 로우를 변경하는 것을 방지한다.하나의 로우를 변경하려면 로우 Lock을 먼저 획득해야 한다.

  - TM Lock → DML 테이블 Lock : 테이블 구조를 변경하지 못하도록 막는 것

  - 오라클에서 말하는 테이블 Lock은, Lock을 획득한 선행 트랜잭션이 해당 테이블에서 현재 어떤 작업을 수행 중인지를 알리는 일종의 푯말이다

  - TX Lock은 트랜잭션마다 오직 한 개씩 획득하는 반면, TM Lock은 트랜잭션에 의해 변경이 가해진 오브젝트 수만큼 획득한다

  - 블로킹 : Lock 경합 발생해 특정 세션이 작업 진행하지 못하고 멈춰 선 경우. 해결 방법은 커밋(또는 롤백)

  - 교착상태 : 투 세션이 각각 Lock 을 설정한 리소스를, 서로 액세스 하려고 마주 보고 진행하는 상황을 말하며, 둘 중 하나가 뒤로 물러나지 않으면 영영 풀릴 수 없다

  - 같은 데이터를 갱신하는 트린잭션이 동시에 수행되지 않도록 설계해야 하고, DML Lock 때문에 동시성이 저하되지 않도록 적절한 시점에 커밋해야 한다

  - 불필요하게 커밋을 너무 자주 수행하면 Snapshot too old 에러를 유발할 가능성이 높아지고, 그에 앞서 LGWR가 로그 버퍼를 비우는 동안 발생하는 log file sync 대기 이벤트 때문에 성능 저하 현상을 겪을 수 있다

반응형