DB Buffer Cache
사용자가 입력한 데이터를 데이터파일에 저장하거나 다시 읽는 과정에서 사용되는 캐시 영역
버퍼 캐시에서 버퍼 블록 엑세스
데이터 파일 ↔ DB Buffer Cache
모두 블록 단위로 처리, 오라클에서의 I/O는 Block 단위로 이루어진다!
Block 단위란 하나의 칼럼만 끌어올릴 수 없고
해당 데이터가 속한 블록 전체를 읽어야 한다는 의미
전에도 강조했지만
SQL의 성능을 제일 좌우하는것은 엑세스하는 블록 개수!
또한 optimizer의 판단에도 가장 큰 영향을 미친다.
DB Buffer Cache에 해당 데이터가 없을 경우
Data File에 가서 해당 데이터를 찾아 DB Buffer Cache로 가져온다는 것은 이미 알고 있음
문제는 HOW?
해당 데이터 블록이 담긴 버퍼 블록을 어떻게 찾는가?
DB Buffer Cache는 Hash Table 구조로 관리됨
DBA = Data Block Address를 Hash 함수에 입력해 나온 값(hash value)을
해당 Hash Bucket에서 Hash Chain을 따라 스캔하다가 거기서 찾아지면 Buffer Cache에서 바로읽고
찾지 못하면 디스크에서 읽어 해시 체인에 연결한 후 읽게된다.
다른 사용자들도 사용할 수 있도록 캐싱해 둠
각 블록에 어떤 데이터가 들어잇다는걸
인덱스마냥 리스트로 만들어놔서 그 리스트는 하나밖에 없어
db file에서 어떤 데이터가 어디에 있다는 딕셔너리에 있음
db buffer안에 어떤 데이터가 어디에 들어있는지 리스트가 있음 이 리스트는 shared pool에 있다. linked list
근데 이 리스트는 한개 밖에 없음
그래서 사용자가 몰릴경우 기다리는 시간이 걸리게 됨
--> db buffer 안에 있어도 속도가 느린 이유가 바로 이것
Hash Chain은 Linked List 구조로 연결되어있으며
하나의 Hash Bucket에 연결된 Buffer Header의 집합이라고 생각하면 된다.
동일한 Hash Value를 갖는 헤더들은 하나의 Hash Bucket=하나의 Hash Chain에 의해 관리된다.
Bucket에 딸린 Buffer Header들은 Buffer에 대한 메타정보를 가지고 있음(Buffer 영역의 Pointer 값, 이 포인터를 이용해 버퍼 블록을 찾아감)
정리하자면!
DBA를 Hash Value로 변환 -> 해당 Hash Bucket에서 Hash Chain을 따라 Scan
각 Hash Chain은 Latch에 의해 보호된다.
DB Buffer Cache는 SGA 즉 공유 메모리 공간이기 때문에 여러 프로세스가 동시에 액세스 하지 못하도록
직렬화시키기 위해 사용되는 Lock 메커니즘이 바로 Latch
래치를 획득 해야지만 블록에 액세스 할 수 있음
Cache Buffer Chains Latch는 DB Cache에 남아있는 Data Block을 찾기 위해 획득해야 하는 Latch
DB Cache Buffer를 탐색이나, 변경하려는 포르세스는 해당 Hash Chain을 관리하는
Cache Buffer Chains Latch를 획득해야한다!
Cache Buffer Chains Latch 하나가 하나 이상의 Hash Chain을 동시에 관리한다.
정리하자면!
Latch는 SGA에 공유되어있는 자료 구조를 보호하는 것이고
그 중에서도 Cache Buffer Chains Latch는 버퍼 캐시에 연결된 체인 구조를 보호
-> 해시 체인을 스캔하거나 해시체인에 블록을 추가 또는 삭제할때 Cache Buffer Chains Latch가 요구된다.
DB Buffer Cache의 블록들의 상태를 관리하기 위해
LRU List = Least Recently Used List를 사용한다
버퍼 캐시가 사용 빈도가 높은 데이터 블록들 위주로 구성될 수 있게 관리
자주 액세스 되는 블록들이 캐시에 더 오래 남아 있도록 관리
크게 두가지로 나눌 수 있는데
LRU List 메인: 사용된 버퍼들의 리스트(Dirty+Free) 보조: free list
LRUW List 메인: Dirty List 보조: DBWR이 기록중인 버퍼들의 리스트(쓰고있는 블록 리스트들)
3가지 상태의 DB Buffer Block 상태
Free Buffer: 비어있는 버퍼 (Clean Buffer 라고도 함)
Dirty Buffer: 아직 디스크에 기록되지 않은 버퍼
Pinned Buffer: 현재 사용중인 버퍼
대기자 목록에서 기다리고 있다고 쓸 때나 작업을 마친후 목록에서 지울 때
모두 latch를 획득해야한다
Cache Buffer Chains Latch 하나가 하나 이상의 Hash Chain을 동시에 관리한다고 했음
해당 버퍼 블록을 찾았으면 빨리 래치를 해제해줘야지 안그러면 다른 사용자가 작업을 못함 -> 래치에 대한 경합발생증가
해당 버퍼 블록에 갔더니 이미 다른 프로세스가 아직 그 버퍼를 사용중일 경우도 있음
동시에 작업 할 수는 없기 때문에
캐시된 버퍼 블록을 읽거나 변경하려는 프로세스는 먼저 버퍼 헤더로부터 버퍼 Lock을 획득해야함
쉽게 말하면 그 블록 내가 쓸것이다! 하고 찜꽁 해두는것이다.
이렇게 해당 버퍼를 찾았지만 다른 프로세스가 이미 버퍼 lock을 점유한채 내용을 갱신중이라면
버퍼 헤더에 버퍼 Lock Wait List(대기자명단)에 자신을 등록한 후 즉, 이 버퍼 Lock을 획득하면 바로 Latch를 해제
버퍼 Lock Wait List에 등록되고 기다리는 동안에 발생하는 대기 이벤트를
buffer busy watis라고 함
이제 버퍼 락을 점유한채 사용하고 있던 프로세스의 작업이 끝나
버퍼 lock이 해제되면 대기자 명단에 있었던 프로세스가 버퍼 lock을 획득한 후 원했던 작업을 진행한다.
작업 완료 후에는 버퍼lock을 해제해야되는데 이때 다른 프로세스와 충돌이 일어날 수 있으므로
해당 버퍼가 속한 Cache Buffer Chains Latch를 다시 획득해야한다.
대기자 목록에서 기다리고 있다고 쓸 때나 작업을 마친후 목록에서 지울 때
모두 latch를 획득해야한다
버퍼 Lock = 자신이 현재 그 버퍼를 사용중임을 표시 -> 버퍼 헤더에 Pin을 걸었다
그래서 버퍼 Lock = 버퍼 pin = Pinned Buffer
buffer pinning은 버퍼를 읽고나서 pin상태를 계속 유지하는것을 뜻함
같은 블록을 계속 반복적으로 읽어야 하는 경우 버퍼 pinning 즉, 계속 pin 상태를 유치한다면
래치 과정없이 논리적 블록 읽기 횟수를 줄일수있다.
같은 블록을 재방문할 가능성이 큰 몇몇 operation을 수행할 때 사용됨
33쪽 더 인덱스하고 다시
버퍼 Lock 의 필요성
오라클은 블럭단위의 I/O이기 때문에 동시 액세스를 방지해야 함 더군다나 DB Buffer Cache는 SGA
따라서 블록 자체로의 진입을 직렬화해버려야한다.
다른 프로세스가 접근하지 못하도록 막는것이 버퍼 lock
ㅔ432
'TUNING' 카테고리의 다른 글
Latch와 Lock (0) | 2013.03.27 |
---|---|
OWI - Oracle Wait Interface (0) | 2013.03.26 |
Optimizer (0) | 2013.03.14 |
SQL AutoTrace & SQL Trace (0) | 2013.03.12 |
SQL 처리 구조 (0) | 2013.03.11 |