◆ 오라클 주요 아키텍처 개요도



오라클 서버는 오라클 인스턴스와 오라클 데이터베이스로 구성되어 있다.

인스턴스는 SGA(Shared Global Area 또는 Shared Global Area)와 Background Process로 이루어진다.

프로세스는 User Process, Server Process, Background Process 의 3종류가 있다.


◆ 오라클 인스턴스
  - 오라클 데이터베이스에 접근하는 수단
  - 하나의 데이터베이스에 하나 이상의 인스턴스가 있을 수 있다.
  - 메모리(SGA)와 백그라운드 프로세스로 이루어져 있다.


◆ Connection과 Session
  - User Process와 Server Process와의 통신을 Connection이라 부름
  - Server Process와 Oracle Server와의 통신을 Session이라 부름


◆ 오라클 데이터베이스
  - 세가지의 파일로 이루어져 있다. (데이터파일, 컨트롤파일, 리두로그파일)
  - 위 세가지의 파일 중 하나라도 이상이 생기면 DB에 장애가 발생한다.



오라클의 메모리 구조는 SGA와 PGA 의 두개로 구성되어 있다.
SGA는 모든 사용자가 공동으로 사용하는 영역이고, PGA는 개별 사용자마다 각자 사용한다.
예를 들어 DB서버에 사용자 10명이 접속해 있다고 할 때 SGA는 1개이고 PGA는 10개이다.


◆ SGA(System Global Area)
  - SGA는 Shared Pool, Database Buffer Cache, Redo Log Buffer로 구성되어 있다.
  - 추가적으로 Large Pool과 Java Pool, Streams Pool(10g에서 추가됨)이 있다.
  - 9i부터 SGA는 동적으로 값을 변경 가능하다. 즉, DB를 껐다 켜지 않고도 변경이 적용된다. 단, 리두로그는 다이나믹이 아니다.
  - SGA의 사이즈와 관련된 파라미터는 SGA_MAX_SIZE이다.


◆ Shared Pool
  - 최근에 실행된 SQL문이나 최근에 사용된 데이터 정의들이 저장되어 있다.
  - Shared Pool은 Library Cache와 Data Dictionary Cache로 구성되어 있다.
  - Shared Pool의 사이즈와 관련된 파라미터는 SHARED_POOL_SIZE이다.
  - 위 사이즈만 결정해주면 Library Cache와 Data Dictionary Cache의 크기를 오라클이 알아서 잡아준다. 따로 주는 것이 아니다.
alter system set SHARED_POOL_SIZE = 64M;

이런 식으로 Shared Pool의 사이즈 변경이 가능


◆ Library Cache
  - 최근에 사용된 SQL이나 PL/SQL문 및 실행계획이 저장되어 있다.
  - LRU(Least Recently Used) 알고리즘에 의해 관리된다.
가게 진열대에 새로 들여온 물건을 놓아야 하는데 이미 진열대가 꽉 차있다고 가정하자.
그때 어떤 행동을 취해야 할까? 그때는 손님이 잘 찾지 않는 것을 빼고 놓으면 된다.
이것이 LRU알고리즘의 개념이다.


◆ Data Dictionary Cache
  - 최근에 사용된 데이터베이스의 정의들(데이터베이스 파일, 테이블, 인덱스, 컬럼, 유저, 권한 등)이 저장되어 있다.
  - 캐싱된 딕셔너리 정보는 쿼리의 응답속도를 향상시킨다.


◆ Database Buffer Cache
  - DB캐시는 데이터파일에서 필요한 블록이 끌어올려져 저장되는 버퍼이다.
  - DB캐시에 있는 각 버퍼의 크기는 오라클 블록들의 크기와 동일해야 한다.
  - DB_BLOCK_SIZE는 기본 블록의 크기와 관련되어 있는 파라미터이다. 이 파라미터를 변경하면 데이터파일과 DB캐시의 블록 크기가 변경이 된다. 단, 주의해야 할 것은 DB블록 사이즈가 처음 8K였는데 이후 사이즈를 변경하고 싶다고 할 때 DB를 지우고 새로 설치할 때 변경하는 것 외에는 방법이 없다. (8i는 기본 2K, 9i는 기본 4K, 10g는 기본 8K)
  - DB_CACHE_SIZE는 DB캐시 전체의 사이즈와 관련된 파라미터이다.
  - LRU 알고리즘에 의해 관리된다.
100명의 사용자가 쿼리를 날렸다면 DB캐시에는 100개의 쿼리에 각각 필요한 데이터들이 올라와져 있어야 한다. 그러나 현실적으로 DB캐시의 용량은 한정되어 있으므로 한번에 다는 못올라온다. 이미 꽉 차 있는데 거기에서 제일 안쓰이는 것을 빠지고 그 다음 기다리던 것이 끌어올려진다.
  - DB_KEEP_CACHE_SIZE는 LRU 알고리즘의 적용을 받지 않는 DB캐시 내의 공간 크기와 관련된 파라미터이다.
LRU 알고리즘은 위에서 보았다시피 가장 마지막에 실행된 녀석들을 남겨놓고 나머지는 다 버리는 것이다.
사용자 한명이 회원 테이블의 회원이 총 몇명인지 알기 위해 select count(*) from 회원;라는 쿼리를 날렸다고 하자. 그리고 기존에 DB캐시에는 사원, 부서, 매출 테이블이 올라와져 있었다고 하자. 그러면 회원 테이블에 대한 데이터가 DB캐시에 없으므로 데이터파일에서 회원 테이블 관련 블록들을 끌어올릴 것이다. 근데 DB캐시 사이즈가 작아서 회원 테이블 하나 올렸을 뿐인데 꽉 찼다고 하자. 그럼 나머지 사원, 부서, 매출 테이블에 대한 것들은 싹 다 버려진다.
문제는 그 다음부터 일어난다. 다시 사원, 부서, 매출에 대한 쿼리가 들어왔을 때 DB캐시에는 또다시 관련 블록들이 끌어올라와져야 한다. 이것이 LRU의 치명적 단점이다.

이것을 해결하기 위해 DB캐시 앞에 Keep캐시 공간을 만들어서 그 안에 놓여진 것들은 LRU알고리즘의 적용을 받지 않게끔 한 것이다.
예를 들어 사원 테이블을 생성할 때 storage keep 옵션을 주면 사원 테이블에 대한 블록이 끌어올려질 때는 Keep 공간으로 들어가게 된다.
  - DB_RECYCLE_CACHE_SIZE는 잠깐 쓰이는 데이터 블록들을 Recycle캐시 공간으로 끌어올리는 것과 관련된 파라미터이다.
DB_KEEP_CACHE_SIZE와는 반대로 이 것은 기존에 DB캐시에 올라와져 있던 사원, 부서, 매출 테이블은 그대로 놔두고, 새로 끌어올려진 회원 테이블에 대한 블록들은 Recycle캐시 공간으로 끌어올리는 것이다.

그러나 실제로 Keep공간이나 Recycle공간을 잘 쓰이지 않으므로 개념만 파악해두도록 한다.

◇ Database Buffer Cache의 3가지 상태
● Pinned Buffer
다른 유저의 서버프로세스가 현재 사용중인 버퍼.
여기엔 절대로 다른 서버프로세스가 이용해선 안된다. 이미 사용중인 메모리는 절대 공유해서 쓸 수 없다.

● Dirty Buffer
커밋은 날렸지만 아직 데이터파일에 내려쓰지 않은 상태.
다른 서버프로세스가 데이터를 변경했지만 아직 저장되지는 않은 상태이다. 절대 다른 프로세스가 변경부분을 덮어써버리면 안된다.

● Free Buffer
말 그대로 프리해서 써도 되는 버퍼.
변경된 내용이 파일로 내려써진 상태이므로 누가 덮어써도 상관없는 상태의 버퍼.
쿼리문이 들어왔을 때 오라클 서버프로세스는 필요한 블록을 DB캐시에서 찾는데 만약 없다면 데이터파일에서 필요한 블록들을 DB캐시로 끌어올린다. 이때 끌어올려주는 녀석이 서버프로세스이다.

현재 필요한 블록갯수가 3개라고 할 때 DB캐시에 3개의 연속된 Free Buffer공간이 있는지 확인을 한다. 이때 DB캐시를 뒤지는 것이 아니라 Free Buffer를 모아놓은 목록을 보는데 이것을 LRU List라고 한다. LRU List에서 연속된 3개의 Free Buffer를 찾으면 그것을 내가 쓰겠다고 그 부분에 락을 걸고 그 자리에 블록들을 끌어올린다.

만약에 연속된 Free Buffer 공간이 없다면 어떻게 될까? 결과는 못끌어올린다. 이때 서버프로세스는 Dirty Buffer를 Free Buffer로 바꾸기 위해 백그라운드 프로세스에게 아직 내려써지지 않은 것들을 내려쓰라고 지시한다. 내려쓴다면 당연히 Dirty Buffer는 Free Buffer로 바뀌므로 그때 끌어올린다.
Dirty Buffer를 모아놓은 목록 또한 존재한다. 이를 LRUW List라고 한다.

만약 끌어올리는 속도가 너무 느리다면 Free Buffer가 부족해서 일어나는 것이다.(Buffer Busy Wait)


◆ Redo Log Buffer
  - 데이터베이스 데이터 블록의 모든 변경사항을 기록하는 버퍼.
  - 주 목적은 복구에 이용된다.
  - 리두로그버퍼 안에 변경된 사항들을 Redo Entry라고 한다.
  - LOG_BUFFER는 리두로그버퍼의 사이즈와 관련된 파라미터이다.


◆ Large Pool
  - 주로 백업복구와 RMAN 작업, 병렬작업 등을 할때 사용된다.
  - LARGE_POOL_SIZE는 라지풀 사이즈와 관련된 파라미터이다.


◆ Java Pool
  - 자바 관련된 컴파일 작업 등을 할 때 사용되는 곳인데 잘 쓰이지는 않는다.(유명무실한 곳...)
  - JAVA_POOL_SIZE는 자바풀의 사이즈와 관련된 파라미터이다.



서버의 메모리 사이즈가 10G라고 한다면 보통 일반적으로 아래와 같은 비율로 준다.


백그라운드 프로세스가 CPU를 많이 잡아먹고 있다고 OS명령어인 Kill을 이용해서 죽여버리면 DB가 뻗어버린다.
그때는 무조건 기다려야 한다.
Posted by 겨울섬
,