버퍼 Lock
버퍼 Lock 이란?
DB 버퍼 캐시 내에서 버퍼 블록을 찾았으면 가급적 빨리 쥐고 있던 래치를 해제해야 한다. 그러지 않으면 하나의 cache buffers chains 래치에 여러 개의 해시 체인이 달렸으므로 래치에 대한 경합 발생 가능성이 증가하게 된다. 그런데 그 버퍼에 먼저 접근한 선행 프로세스가 아직 버퍼를 사용 중이라면 어떻게 해야 할까? 데이터 접합성에 대한 고민이 또 생긴다.
아주 짧은 순간일지라도 두 개 이상의 프로세스가 동시에 버퍼 내용을 읽고 쓴다면 문제가 생길 수 있는 것이다. 이를 막기 위해 캐시된 버퍼 블록을 읽거나 변경하려는 프로세스는 먼저 버퍼 헤더로부터 버퍼 Lock을 획득해야 한다. 버퍼 Lock을 획득했다면 래치를 곧바로 해제한다. 또 다른 언전장치를 마련해 두었으므로 이제 안심하고 블록을 읽고 쓸 수 있다. 버퍼 내용을 읽기만 할 때는 Share 모드, 변경 할 때는 Exclusive 모드로 Lock을 설정한다. 액세스를 직렬화하기 위한 메커니즘이므로 당연히 Exclusive 모드 Lock은 한 시점에 하나의 프로세스만 얻을 수 있다. select 문이더라도 블록 클린아웃이 필요할 때는 버퍼 내용을 변경하는 작업이므로 Exclusive 모드 Lock을 요구한다.
만약 해시 체인 래치를 획득하고 목적한 버퍼를 찾았는데 다른 프로세스가 버퍼 Lock을 Exclusive 모드로 점유한 채 내용을 갱신 중이라면 래치를 쥔 채 기다릴 수는 없다. 그 럴 때는 버퍼 헤더에 있는 버퍼 Lock 대기자 목록에 자신을 등록하고 일단 래치는 해제한다. 이때, 버퍼 Lock 대기자 목록에 등록돼 있는 동안 buffer busy waits 대기 이벤트가 발생한다.
대기자 목록에서 기다리다가 버퍼 Lock이 해제되면 버퍼 Lock을 획득하고, 원했던 작업을 진행한다. 목적한 읽기/쓰기 작업을 완료하면 버퍼 헤더에서 버퍼 Lock을 해제해야 하는데, 이때도 버퍼 헤더를 액세스하려는 다른 프로세스와 충돌이 생길 수 있으므로 해당 버퍼가 속한 체인 래치를 다시 한번 획득한다. 버퍼 Lock을 해제하고 래치를 해제해야 비로소 버퍼 블록 읽기가 완료된다. 읽으려는 블록이 버퍼 캐시에 없을 때는 디스크 I/O까지 수반되므로 하나의 블록 읽기가 얼마나 고비용인지 실감케 한다.
참고로, 유명한 조나단 루이스의 설명에 의하면, 버퍼 블록을 읽을 때 대부분 두 번의 래치 획득을 요하지만 몇몇 오퍼레이션에서는 래치를 쥔 채 버퍼 블록을 읽기 때문에 래치 획득이 한 번만 일어난다고 한다. 이것은 v$sysstat 뷰에서 consistent gets - examination 통계항목으로 측정된다.
버퍼 Pinning
버퍼 Pin과 관련해서 꼭 알아야 할 기능이 있는데, '버퍼Pinning'이 그것이다. 이는 버퍼를 읽고 나서 버퍼 Pin을 즉각 해제하지 않고 데이터베이스 Call이 진행되는 동안 유지하는 기능을 말한다. 같은 블록을 반복적으로 읽을 때 버퍼 Pinning 을 통해 래치 획득과정을 생략한다면 논리적인 블록 읽기 횟수를 획기적으로 줄일 수 있다. 모든 버퍼 블록을 이 방식으로 읽는 것은 아니며, 같은 블록을 재방문할 가능성이 큰 몇몇 오퍼레이션을 수행할 때만 사용한다.