근본없는 코딩
Oracle SGA/Latch(+LOCK?) 본문
1. SGA(System Global Area) 란?
- SGA는 간단하게 오라클서버의 메모리영역이라고 할 수 있습니다.
- SGA는 Oracle의 인스턴스에 대한 데이터와 제어 정보를 가지는 공유 메모리 영역의 집합입니다.
→ 데이터베이스와 이를 액세스하는 프로세스 사이의 메모리 캐시 영역!
[ Database 와 Instance ] ① 실제 사용자가 Database에 접근하면 1개의 Instance가 할당된다. 프로그램의 Thread와같은 개념이다. ② Database는 물리적인 저장장치로 반 영구적이다.하지만 Instance는 소멸성이다. ③ 사용자는 직접적으로 Database에 접근 할 수 없다. 반드시 Instance를 통해서 접근해야하며, Instance는 사용자와 물리적인 Database 간의 다리역할을 해주는 개념이다. |
- SGA는 공유 풀(Shared Pool), 데이터베이스 버퍼 캐쉬(DataBase Buffer Cache), 리두로그 버퍼(Redo Log Buffer) 이 세 가지 와 LARGE POOL과 JAVA POOL, STREAMS POOL, Fixed SGA로 구성되어 있습니다.
- SGA는 오라클의 공유 메모리 영역으로 많은 프로세스가 동시에 데이터를 액세스 합니다. 따문에 사용자 데이터를 보호하는 Lock과 메모리 액세스를 직렬화 하기 위한 Latch가 필요합니다.
1-1. Database Buffer Cache
- 데이터 파일들(Data Files)로부터 읽은 Data Block의 복사본을 담고 있는 영역입니다.
- 데이터 조회와 변경 등의 실제 작업이 일어나는 공간으로, 사용자가 조회 하거나 변경하려는 모든 데이터는 이 곳에 있어야 합니다.
- 여러 사용자가 공동으로 사용하는 곳으로 하나의 블록에 여러 사용자가 동시에 I/O를 시도 할수 있기 때문에, 어떤 사용자의 데이터를 다른 사용자가 훼손하는 등의 문제가 발생 할 수 있습니다. 따라서 Database Buffer Cache Block 상태를 3가지로 나누어 두고 리스트를 통해 관리하고 있습니다.
① Pinned Buffer : 다른 사용자가 사용하고 있는 블록. ② Dirty Buffer : 현재 작업은 진행되지 않지만 다른 사용자가 내용을 변경한 후 아직 데이터 파일에 저장 하지 않은 버퍼. 다른 사용자는 사용 할 수 없다. ③ Free Buffer : 사용 되지 않았거나, Dirty Buffer 였다가 디스크로 저장되어 재사용 할 수 있는 블록. |
– Buffer Block들의 상태를 관리 하기위해 LRU (Least recently Used) List 를 만들어 사용합니다. 가장 사용이 안되거나 이미 작업이 완료 되어서 덮어 써도 되는 블록을 찾아서 그 곳을 덮어쓰게 됩니다.
Oracle은 일반적으로 대용량인 DB Buffer Cache를 빠르게 관리하기 위해서 여러개의 구역으로 나누고 각 구역을 관리하는 Working Data Set을 여러개 생성해서 사용자들이 Free Buffer를 빠르게 찾을 수 있도록 만들어져 있습니다. 그러나 동시 접속 사용자가 많아지면 대기 현상 때문에 작업 속도가 느려지는 문제가 발생합니다. 이렇게 유한한 자원을 여러 Process가 한꺼번에 사용하려고 할 경우 순서를 지키는 것이 중요한데, 이런 경우 순서를 관리하기 위해 Oracle은 Latch라는 것을 사용합니다.
✨ Latch 란 모든 메모리 자원의 사용 순서를 정해주는 역할을 합니다.
1-2. Redo Log buffer
– 데이터에 변경사항이 생길 경우 (DDL이나 DML이 실행 된 경우) 해당 변경 내용을 기록해 두는 역할을 합니다.
– 변경된 내용을 기록하는 메모리 공간을 Redo log buffer 라고 하고, Redo log buffer의 내용을 디스크에서 저장해 주는 파일을 Redo log file 이라고 부릅니다.
– 모든 변경사항이 전부 Redo에 기록 되는 것은 아닙니다. Direct load (SQL Loader, insert /*+ APPEND */) 나 table이나 index 생성시 nologging 옵션을 주면 기록을 하지 않습니다. (nologging 옵션이 있더라도 insert, update, delete는 모두 redo log에 기록됩니다.)
1-3. Shared Pool
– Shared Pool 은 Library Cache 와 Data Dictionary Cache (Row Cache)등의 공간으로 나뉘어 집니다. (11g 부터는 Server Result Cache 라는 부분도 추가)
– Library Cache는 Soft Parse 할 때 사용 되는 공간으로 이미 수행 되었던 SQL문장이나 PL/SQL 문장의 Parse Code와 해당 PL/SQL 문장, 실행 계획 등이 저장되어 있고, LRU 알고리즘으로 관리됩니다.
– Dictionary Cache는 구문분석이나 옵티마이저가 실행계획을 세울 때 사용 되는 주요 Dictionary들이 Row 단위로 Cache 되어 있습니다. LRU 알고리즘으로 관리됩니다.
※ 11g의 Server Result Cache
결과 값을 Cache 해두는 공간. 결과값을 Shared Pool에 저장해두었다가 동일한 Select 가 수행 되었을 경우 DB Buffer Cache 까지 가지 않고, 즉시 Server Reslut Cache 에서 가져가도록 해서 속도를 높이는 역할을 합니다.
이 기능은 기본적으로 사용 안 함으로 되어 있으며, SQL문장에 /*+ result_cache */ 힌트를 사용하여 수동으로 사용하도록 설정되어 있습니다.
파라메터 값의 RESULT_CACHE_MODE를 FORCE로 설정해 두면, 자동으로 Result Cache를 사용합니다.
이론상으로는 성능 개선 효과가 있어야 하나 눈에 띄게 성능이 좋아지지 않습니다.
1-4. Large Pool
– Shared server mode로 Oracle을 운영 할 경우 UGA가 이 곳에 생성됩니다.
– Parallel Excution (병렬처리) 작업을 할 경우 각 Process들간의 Message Buffer 가 이 곳에 생성됩니다.
– RMAN으로 백업이나 복구를 할 경우 RMAN이 사용하는 I/O용 Buffer가 이 곳에 생성됩니다.
1-5. Java Pool
– Java관련 code나 Java Virtual Machine(JVM) 관련 데이터를 저장합니다.
1-6. Streams Pool
1-7. Fixed SGA
– Oracle이 내부적으로 사용하기 위해 생성하는 공간입니다.
– 백그라운드 프로세스들이 필요로 하는 데이터베이스의 전반적인 공유 정보를 가지고 있습니다.
– 각 프로세스들끼리 공유해야만 하는 Lock 정보 저장하고 있습니다.
2. Latch와 Lock
분류 | 래치 (Latch) | 락 (Lock) |
목적 | 메모리 구조에 대한 배타적인 접근을 위함 | 락 모드가 호환 가능하다면, 다수의 프로세스가 동일한 리소스를 공유하는 것을 허용 |
사용 범위 | SGA 내부의 데이터 구조에만 적용 Memory Object를 임시적으로 보호 단일 오퍼레이션으로 메모리 구조에 대한 접근 제어 트랜잭션 단위가 아님 |
테이블, 데이터블록 및 state object와 같은 오브젝트를 보호 데이터베이스의 데이터 또는 메타데이터 접근 제어 트랜잭션 단위 |
획득 방식 | Willing-to-wait 또는 no-wait | null, row share, row exclusive, share, share row exclusive 또는 exclusive |
범위 | SGA 내부에 정보가 존재하며, 로컬 인스턴스에만 볼 수 있음 - 래치는 인스턴스 레벨로 작동 | 데이터베이스 내부에 정보가 존재하며, 모든 인스턴스에서 볼 수 있음 - 락은 데이터베이스 레벨에서 작동 |
복잡도 | 단순한 명령어를 사용하여 구현됨 일반적으로 test-and-set, comapre-and-swap 또는 단순한 CPU 명령어 구현이 쉬움 |
문맥교환(context switch)을 포함한 일련의 명령어들을 사용하여 구현됨 구현이 복잡함 |
지속기간 | 아주 짧은 순간만 지속됨(micro second 단위) | 일정 시간 동안 지속됨(트랜잭션 동안) |
큐 | 프로세스가 래치 획득을 실패한 후 슬립(Sleep) 상태로 들어갈 때, 해당 요청은 큐(Queue)로 관리되지 않으며, 요청한 순서대로 서비스 되지 않음(Latch wait list를 이용하여 큐 방식으로 사용되는 래치들은 예외) | 프로세스가 락 획득을 실패한 후, 해당 요청은 큐(Queue)로 관리되며, 요청한 순서대로 서비스 됨(NOWAIT 모드는 예외임) |
데드락 | 래치는 데드락이 발생되지 않도록 구현됨 | 락은 큐(Queue) 방식을 사용하며, 데드락이 발생될 가능성이 높다. 데드락이 발생될 때마다 트레이스 파일 생성 |
2-1. 래치 획득 방식 (Willing-To-Wait Mode by Spin: WMS)
① Latch Get: 프로세스 A는 해당 래치를 획득한 프로세스가 없으므로 래치를 획득한다.
②Latch Miss: 프로세스 B는 해당 래치를 프로세스 A가 획득하고 있으므로 래치 획득에 실패한다.
③ SPIN (멀티 프로세스 환경에서만 수행) : 프로세스 B는 _SPIN_COUNT의 수 만큼 SPIN을 수행한다.
→ SPIN을 수행한 후에는 다시 래치 획득을 시도한다. _SPIN_COUNT의 기본 값은 2000이며, SPIN으로 인해 CPU 사용량이 증가한다.
④ Sleep: 만일 여러번 SPIN을 재 수행한 후에도 래치 획득에 실패하면, 프로세스 B는 Sleep 상태로 들어가게 된다.
⑤ Wake: 프로세스 B는 일정 시간이 지난 후 다시 깨어나서 래치 획득을 시도한다.
2-2. 래치 획득 방식 (Willing-To-Wait Mode by Posting: WMP)
① Latch Get: 프로세스 A는 해당 래치를 획득한 프로세스가 없으므로 래치를 획득한다.
② Latch Miss: 프로세스 B는 해당 래치를 프로세스 A가 획득하고 있으므로 래치 획득에 실패한다.
③ Wait List 등록: 프로세스 B를 대기 목록에 등록한다.
④ Done Posting: 프로세스 A가 래치를 해지할 때 대기 목록에 알려준다.
⑤ Get Latch: Wait List에 대기중인 프로세스 X,Y,Z,B 중 하나가 Latch를 획득한다. (순서 보장 X)
✨ 상태 확인: V$LATCH - GETS: 최초 시도시 값 1 증가한다. - MISSES: 최초 시도에서 실패한 경우 1 증가 - SPIN_GETS: 획득하게 되면 1 증가 - SLEEPS: 슬립 상태에 빠질 때마다 증가 |
2-3. 래치 획득 방식 (No-Wait)
하나의 Latch를 보유한 Process가 다른 latch를 획득하고자 한다면, 반드시 현재 보유한 latch보다 높은 level의 Latch만을 획득해야 한다. 예를들면, 3이라는 latch를 보유한 process가 1이라는 latch를 추가적으로 획득해야 한다면, Deadlock을 방지하기 위하여 no-Wait 모드로 획득을 시도해야 한다. 만약 No-Wait 모드로 획득 요청 시 실패를 한다면, 기존에 획득하고 있던 3이라는 Latch를 높고 1이라는 Latch를 획득 후 3이라는 Latch를 시도해야 한다.
→ No-Wait 모드는 현재 자신이 가진 Latch보다 낮은 Level의 Latch를 요구할 시에 Deadlock 발생을 방지하기 위하여 획득 시도 후 실패하면 더이상 획득 시도를 하지 않는다는 뜻이다.
✨ 상태 확인: V$LATCH - GETS: 최초 시도시 값 1 증가한다. - IMMEDIATE_GETS: No-wait 모드로 래치 획득에 성공하면 1 증가 - IMMEDIATE_MISSES: 실패 시 1 증가 |
2-4. 래치의 실제 작동 예
① 새로운 SQL문을 실행하고자 하는 프로세스는 SQL을 Shared Pool의 Library Cache 영역에 올려야 한다. 이 때 필요한 Heap 메모리를 할당 받기 위해서 Shared Pool Latch를 획득해야 한다.
② Select 문이 데이터 블록을 읽기 위해서는 데이터 블록의 DBA(Data Block Address)와 클래스에 해당하는 해시 체인에 접근하고자 하는 모든 프로세스는 cache buffers chains latch를 획득해야 한다.
③ DML으로 데이터가 변경될 때는 PGA 영역에 Redo 데이터(Change Vector)를 생성하는데, 이 Change Vector를 Redo Buffer로 복사하기 위해서는 redo copy latch를 획득해야 한다.
🚩 래치와 락의 차이점?
① 래치(Latch)는 락(Lock)보다 좀 더 제한적인 메커니즘을 가지고 있습니다.
→ 예를 들면 락은 보호되어진 데이터에 대해 한 개 이상의 프로세스에게 접근을 허용하지만,
래치는 오직 한개의 프로세스만 접근 가능합니다.
② 락에는 shared mode를 제공하지만, 래치에는 exclusive access(독점 접근)만 허용을 합니다.
③ 락은 큐를 가지고 쌓아두고 순차적으로 수행하지만, 래치는 큐가 없습니다.
→ 따라서 래치를 획득하고자 하는 프로세스들은 성공할 때까지 재 수행 하는 수밖에 없습니다.
④ 래치는 그 자체로 매우 단순한 구조여서(락에 비해) 하나의 메모리 공간을 차지한다. 따라서 래치를 사용한느 프로세스는 아주 작은 연산만으로도 래치를 제어할 수 있다.(효율적)
🚩 오라클에서 락과 레치를 모두 사용하는 이유?
① A라는 세션이 데이터 버퍼 캐쉬에 있는 특정 버퍼 영역을 Update 하기 위해 버퍼 리스트에 대한 래치를 획득하고 버퍼에 접근한다고 가정합니다. ② 이때 B 세션이 해당 버퍼에 대한 Lock을 Exclusive 모드로 점유한 채 데이터를 업데이트 하고 있었다면, A세션은 래치를 반납하고 데이터 버퍼 헤더의 Lock 대기자 목록에 이름을 올려둡니다. → 래치를 반환하는 이유는 B세션이 버퍼 캐쉬를 Lock 걸고 있기 때문에 굳이 래치를 잡고 Spin 하면서 자원을 소모할 필요가 없기 때문입니다. |
위 내용을 생각해보면 데이터 버퍼 캐시의 메타정보를 담고 있는 버퍼 캐시 리스트에는 래치를 사용하고, 실제적인 버퍼에서는 Lock을 사용하는 것을 알 수 있습니다.
🚩 Latch, Lock, Mutex의 비교
- Latch: 물리적인 대상의 리소스에 대해 짧은 시간동안 권한(읽기/쓰기)를 획득하여 작업하고자 할 경우 사용되는 동시성 제어 단위
- Lock: 논리적인 대상에 대한 비교적 긴 시간의 작업 시 사용되는 동시성 제어 단위
- Mutex: 공유 리소스에 대한 단독 액세스 권한을 하나의 스레드에만 부여하는 동기화 기본 형식
항목 | Latch | Lock | Mutex | 비고 |
수행단위 | 물리적 단위 | 논리적 단위 | 물리적 단위 | 논리적 단위란 테이블 혹은 레코드 단위를 의미 |
단순성 | 단순 | 복잡 | 매우단순 | 데이터 구조 및 수행방식면에서 판단 |
관리주체 | Oracle | Oracle | OS | |
Deadlock 발생 | 거의 없음 | 발생 | OS에서 처리 | Latch의 경우 Oracle 내부적으로는 발생X |
복구 | 가능 | 가능 | 복구불가 | Latch의 경우 undo 영역을 가지고 있음 |
원자성 | 보장 | 안됨 | 보장 | 원자성이란 더이상 쪼갤 수 없는 연산 단위 |
SPIN | 존재 | 없음 | 없음 | SPIN은 자원을 획득하기 위해 Retry 하는 행위 |
✨ Mutex?
- 래치의 새로운 대타.
- 오라클 10g R2부터 사용.
- Shared Cursor Operation에서만 사용(library cache latches, library cache pin latches ...)
- 연산 속도가 Latch에 비해 빠르고 OS에 의해 관리되어 짐.
🚩 왜 오라클은 mutex를 사용해야 했을까? . Spin을 수행하지 않게 됨으로써 매우 가벼워짐 . 제어권을 오라클에서 가지지 않고 OS에 넘겨버림으로써 책임을 덜 수 있음 . Deadlock에 대한 모니터링과 부담 감소 . 수행속도가 래치보다 빠름 . 버전이 올라갈수록 복잡해지는 래치 구조로 인해 성능의 부하가 많이 감 |
📌 출처
. https://rastalion.me/oracle-sga/
. https://tawool.tistory.com/237
. https://blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=dangtong76&logNo=140064903533
'✔ Database' 카테고리의 다른 글
데이터베이스 Lock (0) | 2023.12.04 |
---|---|
[ORACLE] 트리거(Trigger) (0) | 2023.06.26 |