다음 포스트: [Oracle] Select 문장의 실행 원리
유저가 DB에 접속해서 Oracle을 시작(startup)
startup 요청을 받은 최초의 Oracle Server Process가 초기화 파라미터(/etc/sysctl.conf
(리눅스), /etc/system
(솔라리스))를 참고해 OS Kernel에게 공유 메모리를 할당해 달라고 요청
이후 SGA가 생성(공유 메모리 할당)되면 OS Kernel이 관리
OS Kernel에게 SGA 생성을 요청한 Oracle Server Process가 종료되어도 SGA는 종료되지 않습니다.
Instance가 종료되어야 SGA가 공유 메모리에서 사라지게 됩니다.
SGA
는 공유 메모리로 구성
되어 여러 Server Process가 공유해서 사용
깃발(Flag)
이라는 의미로 어떤 자원의 현재 사용 여부를 표현
합니다.
메모리는 메모리 블록 단위로 관리되고, 프로세스는 메모리 블록에 접근합니다.
이때 여러 프로세스가 동시에 하나의 메모리 블록에 접근하게 되면 큰 문제가 발생할 수 있습니다(Kernel Panic, Blue Screen)
그래서 Server에서 동작하는 모든 프로세스는 해당 메모리 블록이 사용되고 있는지를 세마포어 상태를 통해 확인
합니다.
메모리 블록마다 세마포어 세트가 할당되어 있습니다.
세마포어 상태는 set/unset
으로 나뉩니다.
만약 set
으로 세팅되어 있다면 해당 메모리 블록은 사용 중
이라는 의미입니다.
나중에 release되어 unset이 되는 순간 세마포어를 set으로 세팅하고 메모리 블록을 사용할 수 있게 됩니다.
SEMMSL
: 세마포어 세트 당 세마포어 최대 개수SEMMNI
: 리눅스 전체에서 설정 가능한 세마포어 세트 최대 개수
. Oracle 권장 값은 100
이상SEMMNS
: 리눅스 전체에서 사용 가능한 세마포어 최대 개수
. 이론적으로 SEMMSL X SEMMNI
값 이상이어야 합니다.SEMOPM
: 1call(1개의 시스템 호출)이 초당 호출 가능한 최대 세마포어 개수
. 보통 SEMMSL
과 동일하게 설정하는 것이 권장됩니다.아래 명령을 통해 세마포어 파라미터가 어떻게 설정되어 있는지 확인할 수 있습니다.
$ ipcs -ls
세마포어 값들은 Oracle사에서 Oracle 버전과 유닉스 버전에 맞는 최적화된 권장값을 알려줍니다.
SHMMAX
세그먼트
)로 한꺼번에 할당100MB
를 쓸 수 있는데 이 파라미터를 20MB
로 설정할 경우 5개의 세그먼트로 나누어서 사용해야 하므로 성능이 떨어집니다.kernel.shmmax
값을 아주 작게 주고 DB에 접속을 시도할 경우 아래와 같은 메시지가 발생할 수 있습니다.$ sqlplus / as sysdba
ERROR:
ORA-12547: TNS:lost contact
또는 아래와 같은 메시지가 발생할 수 있습니다.
ORA-27123: unable to attach to shared memory segment
kernel.shmmax
값을 확인하려면 아래 명령을 수행합니다.2GB
로 설정합니다)$ cat /proc/sys/kernel/shmmax
16777214
파라미터 변경법
/proc
파일시스템에 변경사항을 직접 반영시켜 Server의 재부팅 없이 SHMMAX
값 변경$ echo "2147483648" > /proc/sys/kernel/shmmax
$ cat /proc/sys/kernel/shmmax
2147483648
sysctl
명령어를 사용해 SHMMAX
값 변경$ sysctl -w kernel.shmmax=2147483648
/etc/sysctl.conf
파일에 Kernel 변수 값들을 추가함으로써 변경 사항을 영구적으로 적용. 이 파일을 수정한 후 OS의 재부팅 없이 즉시 적용하려면 root 계정으로 sysctl -p
명령 수행SHMMNI
4096
$ cat /proc/sys/kernel/shmmni
4096
SHMALL
ceil(SHMMAX/PAGE_SIZE)
값보다 큰 값을 사용할 것을 권장2097152 bytes
. i386
기반 Red Hat Linux
의 페이지 사이즈는 4096 bytes
$ cat /proc/sys/kernel/shmall
2097152
SHMMIN
SHMSEG
메모리 할당 방법 중 가장 성능이 좋은 방법입니다.
SGA내 fixed Area
부분은 반드시 전체가 하나의 세그먼트에 할당되어야 합니다.
메모리가 단편화되어 있다
고 표현합니다.
메모리를 정리해서 Oracle이 연속적인 공간을 할당 받을 수 있도록 해 주어야 합니다.
Oracle의 거의 모든 작업이 SGA에서 이루어집니다.
데이터의 조회와 변경 등의 실제 작업이 일어나는 공간으로 사용자가 조회하거나 변경하려는 모든 데이터는 이 곳에 있어야 합니다.
사용자가 데이터를 입력하면 데이터는 하드 디스크의 데이터 파일에 저장되지만,
저장되어 있는 데이터를 조회하거나 변경하려면 그 데이터가 저장되어 있는 데이터 파일의 블록을 복사
한 후 Database Buffer Cache
로 가져와서 작업을 수행합니다.
번거로울 수 있어 보이지만 작업 속도가 높아집니다.
작업 속도가 디스크보다 메모리가 훨씬 빠를 뿐더러,
메모리에 있는 데이터는 다른 사용자에게 공유될 수 있기 때문에 여러 사람이 작업하는 환경일 경우 전체적인 작업 속도가 빨라집니다.
여러 명의 사용자가 같은 곳의 메모리 블록을 동시에 사용할 경우 심각한 장애가 발생할 수 있기 때문에 서로 중복사용이 되지 않도록 잘 관리가 되어야 합니다.
Database Buffer Cache 상태
: 만약 어떤 사용자가 데이터를 조회하거나 변경해야 할 경우 해당 데이터가 이 곳에 없다면 하드 디스크의 데이터 파일에서 필요한 블록을 찾아 Database Buffer Cache로 복사를 해와야 합니다. 하지만 그 전에 Database Buffer Cache의 블록 상태
를 먼저 확인해야 합니다. 여러 사용자가 공동으로 사용하는 곳이므로 하나의 블록에 여러 사용자가 동시에 I/O를 시도할 수 있기 때문입니다.
Pinned Buffer
: 다른 사용자가 현재 사용하고 있는 Buffer 블록Dirty Buffer
: 현재 작업은 진행되지 않지만 다른 사용자가 내용을 변경한 후 아직 데이터 파일에 변경된 내용을 저장하지 않은 Buffer를 의미합니다.Free Buffer
: 사용되지 않았던지(Unused
) Dirty Buffer
였다가 하드 디스크로 저장이 완료(DBWR에 의해 기록됨)되어 재사용할 수 있는 블록을 의미합니다(미사용 Buffer + DBWR에 의해 기록된 Buffer
).LRU(Least Recently Used) List
: 제한적인 메모리 공간을 효율적으로 관리(기존의 블럭에 덮어쓰기)하기 위한 리스트
LRU 알고리즘
을 이용하여 관리하는 리스트입니다.LRU 알고리즘
: 만약 SGA 용량이 100MB인데 사용자들이 변경하고자 하는 자료가 150MB일 때, SGA의 일부분을 덮어 써야 합니다. 이때 가장 최근까지 많이 사용된 것은 지키고 가장 사용이 안된 것은 덮어쓰는(버리는) 알고리즘입니다.메인 리스트
: 사용된 Buffer들의 리스트. Hot/Cold
로 나뉩니다.보조 리스트
: 미 사용된 Buffer들이나, DBWR에 의해 기록된 Buffer들의 리스트(Free List
)만약 어떤 사용자가 데이터 파일의 데이터를 Database Buffer Cache로 가져와야 할 경우가 생긴다면,
(하드 디스크의 데이터 파일에서 필요한 블록을 찾아 DB Buffer Cache로 복사해 오는 작업은 Server Process
가 담당합니다)
free buffer
를 먼저 찾습니다.cold
영역에서 free buffer
를 다시 찾습니다.10G 기준 40%
)만큼 찾고 더이상 free buffer를 찾을 수 없다면 스캔을 멈추고 DBWR
에게 Dirty Buffer
를 내려 쓰라고 요청을 하게 됩니다. 그럼 Dirty Buffer
는 Free Buffer
로 바뀌게 되고, 보조 리스트에 추가하면서 Free Buffer
를 확보합니다.
DBWR
(Database Writer) Process: 변경이 완료된 데이터를 데이터 파일로 저장해주는 백그라운드 프로세스
Latch
: 유한한 자원(EX. Free List
) 을 여러 프로세스가 한꺼번에 사용하려고 할 경우 사용 순서를 관리해줍니다.
Latch
가 별도로 존재합니다.Latch
를 가지고 있어야만 합니다.데이터에 변경사항이 생길 경우(DDL, DML) 해당 변경 내용을 기록해 두는 역할을 합니다.
장애가 발생했을 때 Redo Log
를 이용해 복구할 수 있습니다.
(Redo log
: 돈을 빌려주고 적는 장부와 같은 것)
Redo Log
가 저장되는 메모리 공간을 Redo Log Buffer
라고 합니다.
Redo Log Buffer
가 저장되는 디스크 내의 파일을 Redo Log File
이라고 합니다.
모든 변경사항들이 Redo Log에 기록되는 것은 아닙니다.
Direct Load(SQL Loader, insert /*+ APPEND */)
나 table
, index
생성 시 nologging
옵션을 준다면 Redo Log
에 기록되지 않습니다.
(nologging
옵션을 주고 table
을 생성했다 하더라도 테이블 내에서 발생하는 insert
, update
, delete
는 모두 Redo Log에 기록됩니다)
Redo Log
는 Oracle Recovery의 핵심 요소이지만 전체적인 성능이 저하되는 부작용이 있습니다.
shared_pool_size
파라미터의 크기를 통해 shared pool
의 전체 크기를 설정할 수 있습니다.
Library Cache
와 Dictionary Cache
의 크기는 따로 관리할 수 없습니다.
Library Cache
Soft Parse
할 때 사용되는 공간으로 이미 수행되었던 SQL 문장이나 PL/SQL 문장의 Parse Code
와 해당 SQL/PLSQL 문장
, 실행계획(플랜)
등이 저장되어 있습니다.LRU 알고리즘
으로 관리됩니다.
SQL
: 관계형 데이터베이스에 저장된 데이터에 Access하기 위하여 사용하는 표준언어입니다.PL/SQL
: SQL문을 사용하여 프로그램을 작성할 수 있도록 확장해 놓은 오라클의 Procedural Language이다.
Dictionary Cache
LRU 알고리즘
으로 관리됩니다.Server Result Cache
11g
부터 새로 생긴 영역쿼리의 결과를 저장해두는 영역
으로 Database Buffer Cache 영역까지 가지 않고, Server Result Cache
에서 가져가도록 해서 성능을 향상
시켰습니다.SQL Query Result Cache
: SQL의 결과값을 저장하는 영역PL/SQL Query Result Cache
: PL/SQL의 결과값을 저장하는 영역기존에는 쿼리를 요청하면 Server Process가 디스크로부터 쿼리의 결과값을 SGA의 Database Buffer Cache Block에 저장하고, Database Buffer Cache에서 데이터를 찾아와(
Fetch
: 인출) PGA에서 취합한 후 사용자에게 보여주는 구조였습니다.
Reserved Pool
대용량인 객체가 있을 경우
Shared Pool의 공간이 부족할 때 사용하는 공간입니다.SHARED_POOL_RESERVED_SIZE
파라미터로 용량을 설정하면 됩니다.Shared_Pool_Size
크기의 5% ~ 50%
입니다.v$shared_pool_reserved
를 조회하면 됩니다.REQUEST_FAILURES
값이 증가하면 이 공간이 부족하다는 뜻이므로 SHARED_POOL_RESERVED_SIZE
의 값을 늘려주면 됩니다.REQUEST_MISSES
의 값이 0이거나 증가되지 않는다면 공간이 부족하지 않다는 뜻입니다.SGA의 필수 구성 요소는 아니며 아래와 같은 경우에 사용합니다.
UGA
를 이곳에 생성합니다.Message Buffer
가 이곳에 생성됩니다.RMAN
이 사용하는 I/O용 Buffer
가 이곳에 생성됩니다.SGA의 필수 구성 요소는 아니며 java와 관련해서 code
나 JVM
관련 데이터를 저장하기 위해 생성되는 선택적인 공간입니다.
10g
이상 버전부터 생긴 SGA의 구성 요소입니다.
Streams 기능을 사용할 경우 생성됩니다.
그래서 디폴트 크기는 0
이지만, Streams 기능을 사용하게 되면 Oracle Streams가 동적으로 그 크기를 증가
시킵니다.
Oracle이 내부적으로 사용하기 위해 생성하는 공간입니다.
Background Process들이 필요로 하는 Database의 전반적인 공유 정보
나 각 Process들끼리 공유해야 하는 Lock 정보
와 같은 내용들이 저장되는 영역입니다.
이 공간의 크기는 Oracle이 시작될 때 자동으로 설정되며 사용자나 관리자가 임의로 변경할 수 없습니다.
9i
버전부터 등장한 기능으로 관리자가 필요에 의해서 SGA의 구성요소의 크기를 변경한 후 Oracle Instance의 재기동 없이 즉시 적용할 수 있는 기능입니다.
변경 방법은 alter system set
명령을 사용하면 됩니다.
SYS> alter system set DB_CACHE_SIZE=100M;
동적으로 SGA 영역의 크기를 변경할 때 Oracle에서 메모리를 할당하는 단위입니다.
SGA_MAX_SIZE
라는 파라미터의 크기에 따라 결정됩니다.
9i
SGA_MAX_SIZE
<= 128MB : 1Granule = 4MB
SGA_MAX_SIZE
> 128MB : 1Granule = 16MB
10g
이후SGA_MAX_SIZE
<= 1G : 1Granule = 4MB
SGA_MAX_SIZE
> 1G : 1Granule = 16MB
Oracle에서 현재 사용 중인 SGA 크기
를 확인하려면 show sga
명령을 사용합니다.
SYS> show sga;
Total System Global Area 1660940992 bytes
Fixed Size 8897216 bytes
Variable Size 956301312 bytes
Database Buffers 687865856 bytes
Redo Buffers 7876608 bytes
Total System Global Area
: SGA 전체 용량Fixed Size
: Background Process들이 사용하는 공간Variable Size
: Shared Pool, Large Pool, Java PoolDatabase Buffers
: Database Buffer CacheRedo Buffers
: Redo Log BufferOracle에 설정된 각 파라미터를 조회하고 싶다면 show parameter
명령을 사용합니다.
SYS> show parameter sga_max_size;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
sga_max_size big integer 1584M
SYS> show parameter shared_pool_size;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
shared_pool_size big integer 0
SYS> show parameter db_cache_size;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_cache_size big integer 0
먼저 SGA_MAX_SIZE
의 값을 조회해봅니다.
SYS> show parameter sga_max_size;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
sga_max_size big integer 160M
SGA_MAX_SIZE
는 160M
인 것을 확인했습니다.
이제 shared_pool_size
의 값을 10MB
로 변경해봅시다.
SYS> alter system set shared_pool_size=10m
System altered.
SYS> show parameter shared_pool_size;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
shared_pool_size big integer 12M
SGA_MAX_SIZE
가 160M
로 1G
미만이기 때문에 1Granule
은 4M
입니다.
따라서 4의 배수
로 할당되어 shared_pool_size
는 12M
로 할당되었습니다.
만약 shared_pool_size
를 8M
로 변경하면 어떻게 될까요?
SYS> alter system set shared_pool_size=8M;
System altered.
SYS> show parameter shared_pool_size;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
shared_pool_size big integer 8M
4의 배수
로 할당되므로, 8M
그대로 할당된 것을 확인할 수 있습니다.
PGA(Program Global Area)
는 각 프로세스들이 개별적으로 사용하는 메모리 공간입니다.
SGA가 학교의 운동장이라면,
PGA는 학생들의 개별 사물함입니다.
Oracle에서 동작하는 모든 프로세스들(Server Process, Background Process)은 모두 PGA를 가지고 있습니다.
그 중에서 Server Process가 사용하는 Instance PGA의 아키텍처를 살펴보겠습니다.
다음은 PGA의 세부적인 아키텍처를 살펴보겠습니다.
사용자가 SQL 문장을 수행하면 User Process가 Server Process로 해당 쿼리를 전달합니다. Server Process는 User Process와 관련된 정보를 Session Memory
에 저장하고, 해당 SQL의 Parse
작업을 시작합니다.
Persistent Area
: Bind 변수 값을 저장해두는 공간입니다.Runtime Area
: 쿼리를 수행하는 도중에 데이터를 임시로 저장하는 공간입니다. 예를 들어 100만 건의 데이터를 조회해서 출력해야 할 때, 100만 건 모두가 DB Buffer Cache에서 PGA로 Fetch되어야만 화면에 출력할 수 있는데, 100만 건 모두가 Fetch될 때까지 Runtime Area
에서 데이터를 모읍니다.
Bind 변수
: 사용자로부터 특정 값을 입력 받을 경우 입력 받는 값을 저장할 변수
Sort
, Hash
관련 작업을 수행하는 공간입니다.
8i
이전 버전까지는 PGA의 각 공간을 수동으로 직접 관리했습니다.
9i
부터는 Oracle Server가 자동으로 관리할 수 있는 방법이 등장하게 됩니다.
PGA의 총량
을 지정하는 파라미터인 PGA_AGGREGATE_TARGET
의 값을 설정한 후 WORKAREA_SIZE_POLICY
파라미터를 AUTO
로 설정하면 PGA
를 구성하는 각각의 구성요소의 크기를 Oracle Server가 동적으로 관리하게 됩니다.
(WORKAREA_SIZE_POLICY
를 MANUAL
로 지정하면 기존처럼 수동으로 관리할 수 있습니다)
적절한 PGA 용량 계산 방법
- OLTP 시스템 환경일 경우:
PGA_AGGREGATE_TARGET = (<총 물리 메모리 용량> * 80%) * 20%
- DSS 시스템 환경일 경우:
PGA_AGGREGATE_TARGET = (<총 물리 메모리 용량> * 80%) * 50%
개별 Server Process가 쓸 수 있는 PGA 용량
은 SMM_MAX_SIZE
파라미터로 설정할 수 있습니다.
아래의 명령을 통해 PGA 관련 값들을 조회할 수 있습니다.
SYS> select * from v$pgastat;
NAME VALUE
---------------------------------------------------------------- ----------
UNIT CON_ID
------------ ----------
aggregate PGA target parameter 671088640
bytes 0
aggregate PGA auto target 440423424
bytes 0
global memory bound 104857600
bytes 0
NAME VALUE
---------------------------------------------------------------- ----------
UNIT CON_ID
------------ ----------
total PGA inuse 181725184
bytes 0
total PGA allocated 233025536
bytes 0
maximum PGA allocated 234139648
bytes 0
NAME VALUE
---------------------------------------------------------------- ----------
UNIT CON_ID
------------ ----------
total freeable PGA memory 17563648
bytes 0
MGA allocated (under PGA) 0
bytes 0
maximum MGA allocated 0
bytes 0
NAME VALUE
---------------------------------------------------------------- ----------
UNIT CON_ID
------------ ----------
process count 58
0
max processes count 58
0
PGA memory freed back to OS 6488064
bytes 0
NAME VALUE
---------------------------------------------------------------- ----------
UNIT CON_ID
------------ ----------
total PGA used for auto workareas 0
bytes 0
maximum PGA used for auto workareas 0
bytes 0
total PGA used for manual workareas 0
bytes 0
NAME VALUE
---------------------------------------------------------------- ----------
UNIT CON_ID
------------ ----------
maximum PGA used for manual workareas 0
bytes 0
over allocation count 0
0
bytes processed 29732864
bytes 0
NAME VALUE
---------------------------------------------------------------- ----------
UNIT CON_ID
------------ ----------
extra bytes read/written 0
bytes 0
cache hit percentage 100
percent 0
recompute count (total) 281
0
21 rows selected.
다음 포스트: [Oracle] Select 문장의 실행 원리
참고