h2.3. 버퍼 Lock
h3.(1) 버퍼Lock이란?
Oracle은 Row level을 Lock을 제공하기 때문에 서로 다른 Row를 변경하는 것은 문제가 되지 않는다. 하지만 두개의 Row가 같은 블록 안에 있다면 블록을 동시에 변경하는 것은 안되기 때문에 각 사용자는 개별적으로 Row 변경을 위해 TX Lock을 Exclusive하게 획득했다 하더라도 한 한명의 사용자 만이 블록을 변경하고 있다는 것을 보장 받아야 한다. 이 경우에 획득해야 하는 Lock을 Buffer Lock이라 한다.
만일 Buffer Lock을 획득하지 못하면 다른 Lock들과 마찬가지로 Lock을 획득할 때까지 대기해야 한다.
버퍼Lock을 획득 했다면 래치를 곧바로 해제한다.
버퍼내용을 읽기만 할 때는 Share모드, 변경을 할 때는 Exclusive모드 Lock을 설정한다.

1. 변경하고자 하는 Row에 해당하는 Block 이 존재하는 위치에 찾아가기 위해 cache buffer chains latch를 획득한다.
2. Block을 찾은 해당 Buffer에 대해 Buffer Lock을 획득하고, cache buffers chains latch를 해제한다.
3. 해당 Row에 대해 TX Lock을 획득하고 Row를 변경한다.
4. Buffer Lock을 해제한다.

  • 해시 체인 래치를 획득하고 목적한 버퍼를 찾았는데 다른 프로세스가 버퍼Lock을 Exclusive모드로 점유하고 있다면, 버퍼Lock 대기자 목록에 등록하고 래치를 해제한 후 buffer busy waits 대기 이벤트를 발생한다.

h3.(2) 버퍼핸들

  • 버퍼헤더에 Pin을 설정하려고 사용하는 오브젝트를 일컬음.
  • 버퍼Pin = 버퍼lock : 자신이 해당 버퍼를 사용중임을 표시하는 것.
  • 버퍼핸들을 얻어 버퍼헤더에 있는 소유자 목록에 연결시키는 방식으로 Pin을 설정한다.
  • 버퍼핸들을 얻으려면 cache buffer handles 래치가 필요하다.
  • 오라클은 각 프로세스마다 _db_handles_cached 개수만큼 버퍼 핸들을 미리 할당해주며 기본값은 5이다.

h3.(3) 버퍼Lock의 필요성

  • 오라클의 I/O 단위는 블록이기 때문에 블록에도 Lock이 필요하다. (정합성 보존)
  • Pin된 버퍼 블록은 alter system flush buffer_cache; 명령어를 사용하여 버퍼 캐시 전체를 비우려고 해도 밀려나지 않음.
  • 9i에서는 alter system set events 'immediate trace name flush_cache'; 를 통해 버퍼캐시를 비울 수 있다.

h3.(4) 버퍼 Pining

  • 버퍼를 읽고 나서 버퍼Pin을 즉각 해제하지 않고 데이터베이스 Call이 진행되는 동안 유지하는 기능.
  • 같은 블록을 반복적으로 읽을 때 래치획득 과정을 생략하기 때문에 논리적 블록읽기 횟수를 획기적으로 줄일 수 있음.
  • 같은 블록을 재방문할 가능성이 큰 오퍼레이션을 수행할 때만 사용됨.
  • 하나의 데이터베이스 Call 내에서만 유효함.

Pining의 사용 예

인덱스를 경유해 테이블을 액세스 할 때 인덱스 클러스트링 팩터가 좋다면 같은 테이블 블록을 반복 액세스할 가능성이 크다. (8i)
NL 조인시 Inner테이블을 룩업하기 위해 사용되는 인덱스 루트블록.(9i)
Index Skip Scan에서 브랜치 블록을 거쳐 리프 블록을 액세스 하는 동안. (9i)
NL 조인시 Inner테이블의 인덱스 루트블록 뿐만 아니라 다른 인덱스 블록에 대해서도 Pining을 함. (9i)
DML 수행시 Undo레코드를 기록하는 Undo블록.