이전 포스트: [Oracle] Control File 관리하기
다음 포스트: [Oracle] Tablespace와 Data File 관리하기
데이터에 변경이 발생할 경우 만약에 발생할 장애에 대비해 변경되기 전
의 데이터와 변경된 후
의 데이터를 모두 Redo Log File
에 기록합니다. 복구가 필요할 때 Redo Log File을 이용하게 됩니다.
Write Log Ahead
실제 데이터를 변경하기 전에 Redo Log에 먼저 기록한 후 데이터를 변경합니다.
(DBWR이 작동하기 전 LGWR이 작동하는 것)
Log force at Commit
commit 요청이 들어오면 모든 Redo Record들을 Redo Log File에 기록합니다. 대량의 데이터 변경 후 Commit이 한꺼번에 수행되면 성능에 악영향을 주는 경우가 있어 Delayed Commit(지연된 커밋)이나 Group Commit(아주 짧은 시간 동안 모아서 한꺼번에 commit을 수행)이라는 기술이 있습니다.
Step 1)
사용자가 Update 쿼리를 수행하면 해당 Server Process는 DB Buffer Cache에 원하는 Block이 있는지 확인합니다. 없을 경우 Data File에서 해당 Block을 DB Buffer Cache에 복사합니다. 그 후 해당 Block을 다른 프로세스가 사용할 수 없도록 Lock을 설정한 후 PGA
에서 Redo Change Vector
를 생성합니다.
Redo Change Vector
: 블록 변경에 대한 가장 최소 단위의 트랜잭션.
Change Vector가 모여 Redo Record가 되고, Redo Record가 모여 Transaction이 됩니다.
PGA 상에서 만들어진Redo Change Vector
들은 Redo Record Format으로 row 단위로 Redo Log Buffer에 복사됩니다.
사용자가 commit한 후 checkpoint가 발생하기 전에 DB가 강제 종료되었을 때 해당 데이터를 Roll Forward하는 내용 + 사용자가 Roll Backward 후 아직 Rollback이 완료되지 않은 상태에서 DB가 강제 종료되었을 때 Rollback되지 못한 데이터를 모두 Rollback 시켜주는 내용
Step 2)
Server Process는 Redo Change Vector
를 생성한 후에 Redo Log Buffer에서 필요한 용량을 계산합니다. 그리고 PGA에서 생성한 Redo Change Vector
를 Redo Log Buffer
에 복사하기 위해 필요한 Latch
를 획득해야 합니다.
Redo Log Buffer에 내용을 쓰기 위해선 두 가지 Latch
를 확보해야 합니다. 첫 번째는 Redo Copy Latch
입니다. 만약 여러 개의 Server Process가 동시에 데이터를 변경해야 한다면 경합이 발생할 수 있고 성능이 느려지게 됩니다. 여러 Server Process는 Redo Change Vector
가 모두 Redo Log Buffer
에 기록될 때 까지 계속 Redo Copy Latch
를 가지고 있어야 하기 때문에 여러 개가 존재하게 됩니다. _log_simultaneous_copies
라는 히든 파라미터를 통해 Redo Copy Latch
의 개수 조정이 가능합니다.
현재 시스템의 Redo Copy Latch
현황은 아래와 같이 조회 가능합니다.
SQL> col name for a13;
SQL> select name, gets, misses, immediate_gets, wait_time
2 from v$latch_children
3 where name='redo copy';
Redo Copy Latch
의 개수를 많이 늘린다고 성능에 도움이 되지는 않습니다. 만약 Redo Log 관련 대기 현상이 많이 생긴다면 Latch
의 문제인지 아니면 Redo Log Buffer
나 Redo Log File
자체에 문제가 있는 것인지 잘 파악한 후 조치를 취해야 합니다. Redo Copy Latch
를 획득하기 위해 대기를 하는 경우 Latch:redo copy
의 값이 증가될 것입니다. 하지만 Redo Copy Latch
는 Redo Change Vector
가 모두 기록될 때 까지 가지고 있는 것이므로 Redo Copy Latch 획득 후의 단계에서 문제가 발생했을 수도 있습니다.
Step 3)
Server Process는 Redo Copy Latch
획득 후 두 번째 Latch
인 Redo Allocation Latch
를 획득해야 합니다. Redo Log Buffer를 여러 개의 공간으로 나누어서 각 공간별로 Redo Allocation Latch
를 할당합니다(Shared Redo Strand
).
Shared Redo Strand
기능과 관련해서 중요한 것은 Redo Log Buffer
를 몇 개로 나누는가 입니다. 10g
부터 기존의 _LOG_PARALLELISM
파라미터의 값(Redo Log Buffer를 몇 개로 나누는가)을 동적으로 관리할 수 있도록 _LOG_PARALLELISM_DYNAMIC
파라미터가 추가되었습니다. _LOG_PARALLELISM_DYNAMIC
를 TRUE
로 설정할 경우 오라클이 동적으로 나누는 개수(strand
)를 관리합니다. _LOG_PARALLELISM
에 대한 권장값은 (CPU 개수 / 8)
입니다.
Redo Allocation Latch
는 아래와 같은 방법으로 조회가 가능합니다.
SQL> select count(*)
2 from v$latch_children
3 where name='redo allocation';
Shared Redo Strand
보다 확장된 개념이 10g
부터 도입된 Private Redo Strand
기능입니다.
Redo Log Buffer를 쪼개는 것이 아닌 Shared Pool을 쪼개서
각 Server Process 만의 독립된 Private Strand 공간을 만들고 그곳에 Redo Change Vector
를 생성한 후 필요할 경우 LGWR
이 Redo Log File
에 바로 기록합니다. 기존에 PGA에서 Redo Log Buffer로 Redo Change Vector를 복사할 필요가 없어 성능을 더욱 향상시킬 수 있습니다. 이 기능을 다른 말로 zero copy redo
라고 합니다. _LOG_PRIVATE_PARALLELSIM
파라미터를 TRUE
로 설정하면 활성화 됩니다.
Step 4)
Server Process는 특정 상황이 되면 Redo Writing Latch
를 확보한 후 LGWR
에게 Redo Log Buffer에 기록된 내용들(Redo Entries(Redo Change Vector)
)을 Redo Log File
에 기록하라고 요청합니다. 이후 Redo Log Buffer의 Redo Entries(Redo Change Vector)
는 삭제(Flush
)됩니다.
LGWR
이 작동하는 경우는 아래와 같습니다.
1. 3초마다
LGWR 프로세스
는 할 일이 없을 경우 sleep 상태로 되었다가 rdbms ipc message라는 대기 이벤트의 time out이 되는 시점인 3초마다 한 번씩 wake up해서 Redo Log Buffer에서 Redo Log File로 기록해야 할 내용이 있는지 찾게 됩니다. 그래서 기록해야 할 부분이 있으면 Redo Log File에 기록한 후 Redo Log Buffer에서 해당 내용을 Flush
합니다.
2. Redo Log Buffer의 전체 크기의 1/3
이 찼거나 1M
이 넘을 경우
Server Process는 Redo Log Buffer를 할당 받을 때마다 현재 사용된 Log Buffer의 Block 수를 계산합니다. 만약 현재 사용된 Log Buffer의 Block 수
가 _LOG_IO_SIZE
의 값보다 클 경우 LGWR
에게 Redo Log Buffer
의 내용을 Redo Log File
에 기록하도록 요청합니다. LGWR이 자주 작동할 수록 안정성은 높아지나 성능이 낮아질 수 있어 적절하게 잘 조정해야 합니다.
3. 사용자가 commit 또는 rollback을 수행할 때
사용자가 commit, rollback을 수행하게 되면 내부적인 관리번호인 SCN
이 생성되어 해당 트랜잭션에 할당되고 관리됩니다.
4. DBWR이 LGWR에게 쓰기를 요청할 때
DBWR이 DB Buffer Cache의 Block을 Data File로 기록해야 할 때 Differed Write Queue
에 먼저 기록한 후 LGWR 프로세스를 먼저 수행시켜서 해당 Redo Log를 먼저 Redo Log File에 내려쓴 후 Data File에 DB Buffer Cache의 Block을 기록하는 방식으로 Sync를 맞추게 됩니다.
LGWR이 Redo Log Buffer의 내용을 Redo Log File로 내려 쓸 때 DBWR과 마찬가지로 Block 단위로 내려씁니다. 하지만 LGWR은 DB_BLOCK_SIZE
에 의해 결정되는 것이 아닌 OS BLOCK SIZE
에 의해 결정되며, OS 종류에 따라 값이 다를 수 있습니다.
아래는 OS BLOCK SIZE
를 조회하는 방법입니다.
SQL> select max(lebsz) from sys.x$kccle;
Redo Log File은 그룹과 멤버라는 개념으로 관리됩니다. 같은 내용을 여러 곳에 중복으로 저장해서 안정성을 높입니다. 여기서 멤버는 하나의 Redo Log File
을 의미합니다.
위 그림에는 그룹
이 3개
가 있고, 각 그룹에는 멤버
가 2개
씩 존재합니다. 같은 그룹에 속한 멤버들은 같은 내용을 담고 있어 하나의 멤버가 삭제 또는 장애가 발생해도 데이터가 안전하게 지켜질 수 있습니다. 물론 2개의 멤버가 모두 삭제되거나 장애가 발생하면 데이터는 손실되기 때문에 한 그룹에 멤버의 수를 더 추가할 수도 있습니다. 하지만 멤버의 수를 무작정 늘리게 되면 기록시간이 늘어나 부하를 줄 수 있으므로 적절한 멤버 수를 정해야 합니다. 1개의 그룹에 멤버의 수가 1개인 것은 문제가 되지는 않으나 권장 사항이 아닙니다. 권장 사항은 최소 3개의 그룹
에 최소 2개의 멤버
로 구성하는 것입니다.
Oracle에서 LGWR이 Redo Log Buffer의 내용을 Redo Log File에 내려쓰다가 해당 파일이 가득 차게 되면 다음 그룹
으로 자동으로 넘어가게 됩니다. 이 과정을 Log Switch
라고 합니다.
Log Switch
가 발생하면 checkpoint 신호
가 발생합니다. checkpoint 신호
가 발생하면 DBWR
이 동작해 DB Buffer Cache에서 Data File로 저장되지 못한 변경사항들을 내려씁니다. 그리고 이 정보들을 Control File과 Data File에 반영합니다. Log Switch가 일어나는 순서는 라운드 로빈(Round Robin)
방식입니다.
LGWR은 Redo Log File에 내용을 기록할 때 그룹에 멤버가 여러 개일 경우 병렬로 동시에 같은 내용을 기록합니다.
(직렬
은 하나의 기록이 끝나면 다른 기록을 시작한다는 의미이고, 병렬
은 동시에 기록한다는 의미입니다)
만약 병렬쓰기 도중에 Redo Log File이 삭제되었다든지 Block에 문제가 생겼다든지 해서 문제가 발생할 경우 LGWR은 각 오픈 로그 멤버의 상태를 조사해서 어떤 파일에 에러가 발생했는지 알아냅니다. 그리고 장애가 난 멤버는 Control File
에 STALE
이라는 상태로 기록됩니다. Trace File
에는 ORA-00346
에러를 기록합니다.
만약 하나의 로그 파일에서 4개 이상의 에러를 만나면 LGWR은 그 파일을 닫고 더 이상 그 파일에 내용을 기록하지 않습니다. LGWR이 어떠한 로그 파일에도 내용을 기록할 수 없는 상황이라면 ORA-00340
에러가 발생하고, shutdown abort
로 강제 종료되며 더이상 startup 되지 않습니다.
Redo Log File
의 권장 크기는 일반적으로 정해져 있지 않고, 각 서버의 실정에 맞게 사용합니다. Redo Log File
의 크기가 너무 작다면 Log Switch
가 자주 발생하게 되어 운영 성능이 저하될 수 있고, 반대로 너무 크다면 데이터 손상 가능성이 커집니다. 일반적으로 1시간에 2~3회 발생
하는 것을 권장하지만 업무 환경에 맞게 설정하는 것이 가장 중요합니다.
Alert Log에 checkpoint not completed.
라는 메시지는 Log Switch
가 너무 빈번하게 일어나 DBWR이 이전에 발생한 Checkpoint 내용을 Data File에 다 기록을 못한 상태에서 Log Switch
가 발생할 경우 주로 나타납니다. 해당 메시지가 나오면 Redo Log File
의 크기나 그룹의 개수가 작다는 의미이므로 멤버의 크기를 늘려주거나 그룹을 더 만들어주어야 합니다.
SQL> alter database add logfile group 4
2 '/app/oracle/oradata/testdb/redo04_a.log` size 5M;
SQL> alter database add logfile member
2 '/app/oracle/oradata/testdb/redo04_b.log` to group 4;
SQL> alter database drop logfile member
2 '/app/oracle/oradata/testdb/redo04_b.log';
SQL> alter database drop logfile group 4;
SQL> alter system switch logfile;
SQL> alter system checkpoint;
만약 ASM이 아닌 일반 OS 파일 시스템으로 oracle을 설치했다면 3, 4번 과정에서 Member와 Group을 삭제해도 실제 파일은 지워지지 않습니다. 단지 Control File 안에 있는 해당 그룹과 멤버의 정보만 지울 뿐 실제 파일은 지우지 못합니다. 그래서 OS 명령어를 통해 해당 파일을 직접 지워야 합니다.
Redo Log File의 상태는 CURRENT / ACTIVE / INACTIVE
가 있습니다.
CURRENT
: 현재 LGWR이 내용을 기록하고 있는 상태를 말합니다.ACTIVE
: Redo Log File의 내용이 아직 DB Buffer Cache에서 Data File로 저장이 되지 않아 Redo Log File이 지워지면 안되는 상태입니다.INACTIVE
: Redo Log File의 내용이 DB Buffer Cache에서 Data File에 모두 저장되어 지워져도 되는 상태입니다.만약 DBA가 Redo Log File을 삭제하고 싶다면 반드시 INACTIVE
상태로 만들고 삭제를 수행해야 합니다.
절대! OS 명령어로 실제 파일을 먼저 삭제하면 안됩니다.
Step 1) 현재 상태 확인하기
SQL> !vi log.sql
set line 200
col group# for 999
col mb for 999
col member for a45
col seq# for 999
col status for a8
col arc for a5
SELECT a.group#, a.member, b.bytes/1024/1024 MB, b.sequence# "SEQ#", b.status, b.archived "ARC"
FROM v$logfile a, v$log b
WHERE a.group#=b.group#
ORDER BY 1,2
/
:wq!
SQL> @log
Step 2) 신규 그룹 / 멤버 추가하기
SQL> alter database add logfile group 4
2 '/ORA19/app/oracle/oradata/ORACLE19/redo04_a.log' size 5M;
Database altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC
------ --------------------------------------------- ---- ---- -------- -----
1 /ORA19/app/oracle/oradata/ORACLE19/redo01.log 200 7 CURRENT NO
2 /ORA19/app/oracle/oradata/ORACLE19/redo02.log 200 5 INACTIVE YES
3 /ORA19/app/oracle/oradata/ORACLE19/redo03.log 200 6 INACTIVE YES
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_a.l 5 0 UNUSED YES
og
SQL> alter database add logfile member
2 '/ORA19/app/oracle/oradata/ORACLE19/redo04_b.log' to group 4;
Database altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC
------ --------------------------------------------- ---- ---- -------- -----
1 /ORA19/app/oracle/oradata/ORACLE19/redo01.log 200 7 CURRENT NO
2 /ORA19/app/oracle/oradata/ORACLE19/redo02.log 200 5 INACTIVE YES
3 /ORA19/app/oracle/oradata/ORACLE19/redo03.log 200 6 INACTIVE YES
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_a.l 5 0 UNUSED YES
og
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_b.l 5 0 UNUSED YES
og
SQL> alter system switch logfile;
System altered.
-- 수동으로 checkpoint 신호를 줘서 DBWR이 동작하도록 하기
SQL> alter system checkpoint;
System altered.
-- 이전에 ACTIVE였던 그룹이 INACTIVE로 변경된 것을 확인할 수 있습니다.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC
------ --------------------------------------------- ---- ---- -------- -----
1 /ORA19/app/oracle/oradata/ORACLE19/redo01.log 200 7 INACTIVE YES
2 /ORA19/app/oracle/oradata/ORACLE19/redo02.log 200 5 INACTIVE YES
3 /ORA19/app/oracle/oradata/ORACLE19/redo03.log 200 6 INACTIVE YES
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_a.l 5 8 CURRENT NO
og
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_b.l 5 8 CURRENT NO
og
Step 3) 기존 멤버 삭제/ 그룹 삭제하기
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC
------ --------------------------------------------- ---- ---- -------- -----
1 /ORA19/app/oracle/oradata/ORACLE19/redo01.log 200 7 INACTIVE YES
2 /ORA19/app/oracle/oradata/ORACLE19/redo02.log 200 5 INACTIVE YES
3 /ORA19/app/oracle/oradata/ORACLE19/redo03.log 200 6 INACTIVE YES
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_a.l 5 8 CURRENT NO
og
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_b.l 5 8 CURRENT NO
og
SQL> alter system switch logfile;
System altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC
------ --------------------------------------------- ---- ---- -------- -----
1 /ORA19/app/oracle/oradata/ORACLE19/redo01.log 200 7 INACTIVE YES
2 /ORA19/app/oracle/oradata/ORACLE19/redo02.log 200 9 CURRENT NO
3 /ORA19/app/oracle/oradata/ORACLE19/redo03.log 200 6 INACTIVE YES
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_a.l 5 8 ACTIVE YES
og
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_b.l 5 8 ACTIVE YES
og
-- 수동으로 checkpoint 신호를 줘서 DBWR이 동작하도록 하기
SQL> alter system checkpoint;
System altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC
------ --------------------------------------------- ---- ---- -------- -----
1 /ORA19/app/oracle/oradata/ORACLE19/redo01.log 200 7 INACTIVE YES
2 /ORA19/app/oracle/oradata/ORACLE19/redo02.log 200 9 CURRENT NO
3 /ORA19/app/oracle/oradata/ORACLE19/redo03.log 200 6 INACTIVE YES
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_a.l 5 8 INACTIVE YES
og
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_b.l 5 8 INACTIVE YES
og
SQL> alter database drop logfile member
2 '/ORA19/app/oracle/oradata/ORACLE19/redo04_b.log';
Database altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC
------ --------------------------------------------- ---- ---- -------- -----
1 /ORA19/app/oracle/oradata/ORACLE19/redo01.log 200 7 INACTIVE YES
2 /ORA19/app/oracle/oradata/ORACLE19/redo02.log 200 9 CURRENT NO
3 /ORA19/app/oracle/oradata/ORACLE19/redo03.log 200 6 INACTIVE YES
4 /ORA19/app/oracle/oradata/ORACLE19/redo04_a.l 5 8 INACTIVE YES
og
-- 실제 파일은 삭제되지 않은 상태
SQL> !ls -al /ORA19/app/oracle/oradata/ORACLE19/
total 2126520
drwxr-x---. 2 oracle dba 4096 Nov 2 20:01 .
drwxr-x---. 3 oracle dba 22 Nov 2 18:45 ..
-rw-r-----. 1 oracle dba 10600448 Nov 2 20:06 control01.ctl
-rw-r-----. 1 oracle dba 209715712 Nov 2 20:02 redo01.log
-rw-r-----. 1 oracle dba 209715712 Nov 2 20:06 redo02.log
-rw-r-----. 1 oracle dba 209715712 Nov 2 19:35 redo03.log
-rw-r-----. 1 oracle dba 5243392 Nov 2 20:05 redo04_a.log
-rw-r-----. 1 oracle dba 5243392 Nov 2 20:05 redo04_b.log
-rw-r-----. 1 oracle dba 576724992 Nov 2 20:05 sysaux01.dbf
-rw-r-----. 1 oracle dba 734011392 Nov 2 20:05 system01.dbf
-rw-r-----. 1 oracle dba 20979712 Nov 2 19:33 temp01.dbf
-rw-r-----. 1 oracle dba 209723392 Nov 2 20:05 undotbs01.dbf
-rw-r-----. 1 oracle dba 5251072 Nov 2 20:05 users01.dbf
-- 수동으로 파일 삭제
SQL> !rm -rf /ORA19/app/oracle/oradata/ORACLE19/redo04_b.log
-- 파일이 잘 삭제되었는지 확인
SQL> !ls -al /ORA19/app/oracle/oradata/ORACLE19/
total 2121396
drwxr-x---. 2 oracle dba 4096 Nov 2 20:06 .
drwxr-x---. 3 oracle dba 22 Nov 2 18:45 ..
-rw-r-----. 1 oracle dba 10600448 Nov 2 20:06 control01.ctl
-rw-r-----. 1 oracle dba 209715712 Nov 2 20:02 redo01.log
-rw-r-----. 1 oracle dba 209715712 Nov 2 20:06 redo02.log
-rw-r-----. 1 oracle dba 209715712 Nov 2 19:35 redo03.log
-rw-r-----. 1 oracle dba 5243392 Nov 2 20:05 redo04_a.log
-rw-r-----. 1 oracle dba 576724992 Nov 2 20:05 sysaux01.dbf
-rw-r-----. 1 oracle dba 734011392 Nov 2 20:05 system01.dbf
-rw-r-----. 1 oracle dba 20979712 Nov 2 19:33 temp01.dbf
-rw-r-----. 1 oracle dba 209723392 Nov 2 20:05 undotbs01.dbf
-rw-r-----. 1 oracle dba 5251072 Nov 2 20:05 users01.dbf
-- member가 1개인 group의 member를 지우려 하면 에러가 발생합니다. 그룹을 지워야 합니다.
SQL> alter database drop logfile member
2 '/ORA19/app/oracle/oradata/ORACLE19/redo04_a.log'
3 ;
alter database drop logfile member
*
ERROR at line 1:
ORA-00361: cannot remove last log member /ORA19/app/oracle/oradata/ORACLE19/redo04_a.log for group 4
SQL> alter database drop logfile group 4;
Database altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC
------ --------------------------------------------- ---- ---- -------- -----
1 /ORA19/app/oracle/oradata/ORACLE19/redo01.log 200 7 INACTIVE YES
2 /ORA19/app/oracle/oradata/ORACLE19/redo02.log 200 9 CURRENT NO
3 /ORA19/app/oracle/oradata/ORACLE19/redo03.log 200 6 INACTIVE YES
-- 실제 파일은 삭제되지 않은 상태
SQL> !ls -al /ORA19/app/oracle/oradata/ORACLE19/
total 2121396
drwxr-x---. 2 oracle dba 4096 Nov 2 20:06 .
drwxr-x---. 3 oracle dba 22 Nov 2 18:45 ..
-rw-r-----. 1 oracle dba 10600448 Nov 2 20:08 control01.ctl
-rw-r-----. 1 oracle dba 209715712 Nov 2 20:02 redo01.log
-rw-r-----. 1 oracle dba 209715712 Nov 2 20:07 redo02.log
-rw-r-----. 1 oracle dba 209715712 Nov 2 19:35 redo03.log
-rw-r-----. 1 oracle dba 5243392 Nov 2 20:05 redo04_a.log
-rw-r-----. 1 oracle dba 576724992 Nov 2 20:05 sysaux01.dbf
-rw-r-----. 1 oracle dba 734011392 Nov 2 20:05 system01.dbf
-rw-r-----. 1 oracle dba 20979712 Nov 2 19:33 temp01.dbf
-rw-r-----. 1 oracle dba 209723392 Nov 2 20:05 undotbs01.dbf
-rw-r-----. 1 oracle dba 5251072 Nov 2 20:05 users01.dbf
-- 수동으로 파일 삭제
SQL> !rm -rf /ORA19/app/oracle/oradata/ORACLE19/redo04_a.log
-- 파일이 잘 삭제되었는지 확인
SQL> !ls -al /ORA19/app/oracle/oradata/ORACLE19/
total 2116272
drwxr-x---. 2 oracle dba 4096 Nov 2 20:08 .
drwxr-x---. 3 oracle dba 22 Nov 2 18:45 ..
-rw-r-----. 1 oracle dba 10600448 Nov 2 20:08 control01.ctl
-rw-r-----. 1 oracle dba 209715712 Nov 2 20:02 redo01.log
-rw-r-----. 1 oracle dba 209715712 Nov 2 20:08 redo02.log
-rw-r-----. 1 oracle dba 209715712 Nov 2 19:35 redo03.log
-rw-r-----. 1 oracle dba 576724992 Nov 2 20:05 sysaux01.dbf
-rw-r-----. 1 oracle dba 734011392 Nov 2 20:05 system01.dbf
-rw-r-----. 1 oracle dba 20979712 Nov 2 19:33 temp01.dbf
-rw-r-----. 1 oracle dba 209723392 Nov 2 20:05 undotbs01.dbf
-rw-r-----. 1 oracle dba 5251072 Nov 2 20:05 users01.dbf
commit이 발생하면 해당 트랜잭션은 고유한 번호를 부여받아 관리됩니다. 이 번호를 SCN(System Commit Number)
라고 부릅니다. Oracle은 SCN 번호를 가지고 트랜잭션을 관리하면서 장애 발생시 복구도 수행합니다. Instance Recovery 때나 사용자가 Recover 명령을 실행할 때 Oracle은 SCN 정보를 사용해 데이터베이스에 문제가 있는지 없는지를 판별하고 문제가 있다고 판단될 경우 복구를 수행하게 됩니다.
SCN은 SCN base(4bytes) + SCN Wrap(2bytes)으로 구성되어 있습니다. 초당 16,384회를 발생시켜도 약 534년 정도를 쓸 수 있는 양(281,474,976,710,656)이 제공됩니다. SCN base 값이 모두 사용되면 SCN Wrap 값이 하나씩 증가되고 만약 SCN이 모두 사용되어도 다시 0으로 리셋된 후 새로운 Incarnation
으로 할당되어 다시 시작됩니다.
SCN은 kcmgas
라는 함수(function
)으로 구현됩니다. 아래와 같이 여러 곳에 마지막 SCN
이 기록됩니다.
Block Cleanout
시 마지막 SCN을 각 Block에 기록
Block Cleanout
: commit이 완벽하게 수행되기 위해 Data Block에 걸려있는 Lock이 해제되는 과정.
Delayed Block Cleanout
)Data Block의 Transaction Layer 안에 있는 ITL(Interested Transactino List) Entries에 Commit된 SCN 정보를 기록commit 관련 파라미터를 조회하는 방법은 아래와 같습니다.
SQL> show parameter commit;
commit_point_strength
: 분산 데이터베이스 환경에서 2-phase-commit에서 사용합니다.commit_write
: 사용자가 commit을 하게 되면 LGWR이 해당 트랜잭션을 Redo Log Buffer에서 Redo Log File에 기록하는데 여기에는 4가지
방식이 있습니다. WAIT
: 변경된 트랜잭션이 Redo Log File에 기록될 때까지 기다립니다.NOWAIT
: WAIT와 반대로 Redo Log File에 기록될 때까지 기다리지 않습니다.IMMEDIATE
: commit 요청이 들어오면 즉시 Redo Log File에 기록하기 시작합니다.BATCH
: commit 요청이 들어오더라도 일정 시간 동안 모아서 한꺼번에 기록합니다.2개씩 조합
해서 사용합니다. 예를 들어 IMMEDIATE + WAIT
라면 commit 요청 즉시 Redo Log File에 기록하고 기록이 다 될 때까지 기다린다는 의미입니다. NOWAIT
, BATCH
의 경우 Redo Log File에 기록이 완료되지 않아도 다른 작업을 할 수 있도록 성능을 높이는 비동기식 커밋(Asynchronous Commit
)이라고 합니다. 동기식 커밋에 비해 성능은 좋지만 데이터의 안정성(데이터의 보존 정도)은 떨어집니다. NOWAIT
, BATCH
은 트랜잭션이 많은 OLTP
환경에서 정말 조심해서 사용해야 합니다.SCN의 또 다른 이름으로 System Change Number이 있습니다. Data File, Redo Log File, Control File 간의 동기화 정보를 맞추기 위해 사용됩니다.
Commit된 데이터가 Data File에 어디까지 저장했는지가 기록되어 있는 것이 Checkpoint
입니다.
예를 들어 SCN이 100번까지 commit 되었는데, checkpoint 정보가 90번이라면 SCN 90번 트랜잭션까지 Data File에 저장 되었다고 확인할 수 있습니다.
Checkpoint 정보는 Data File의 복구를 결정하는 기초적인 정보입니다. Control File과 Data File의 Checkpoint 정보를 비교하고 서로 정보가 다르면 틀린 부분을 Online Redo Log / Archived Redo Log를 참조해서 복구합니다.
Checkpoint의 종류는 아래와 같습니다. 여러 종류의 Checkpoint는 저마다의 우선 순위가 존재합니다. 우선 순위가 높은 경우 Fast Checkpoint
로 분류하고, 우선 순위가 낮을 경우 Low Checkpoint
로 분류해서 두 가지가 동시에 발생할 경우 Fast Checkpoint
부터 진행합니다. 보통 database shutdown, tablespace begin backup, alter system checkpoint
등의 명령어로 발생되는 Checkpoint는 Fast Checkpoint로 분류되어 Dirty Buffer들이 DB Buffer Cache에서 Data File로 즉시
저장되는데 이것을 Full Checkpoint
라고도 합니다. 반대로 Low Checkpoint
의 경우 즉시 Data File로 내려 쓰는 것이 아니라 어딘가에 기록
해 둔 후 Background로 내려 쓰게 되는데 이를 Incremental Checkpoint
라고 합니다.
Database / Global Checkpoint
이 Checkpoint가 발생하면 DB Buffer Cache 내
에 있는 모든 저장 안된 Dirty Buffer들의 내용을 전부 Data File로 저장합니다. 저장된 SCN 중 가장 번호가 큰 SCN 번호를(Checkpoint SCN
이라고 합니다) Control File
과 Data File Header
부분에 기록합니다.
Thread Checkpoint / Logical Checkpoint
해당 Thread 내
의 저장되지 않은 모든 Dirty Buffer들을 Data File로 전부 내려쓰게 됩니다. 이 Checkpoint는 Log Switch
가 발생하면 생깁니다. RAC 환경의 경우 각 노드 별로 다르게 발생하고, Single 환경에서는 Database Checkpoint와 같은 역할입니다.
Data File Checkpoint
특정 Data File
에만 발생하는 Checkpoint입니다. 해당 Tablespace를 Offline
하거나, Begin Backup
수행 시 발생하게 됩니다. 이 Checkpoint가 발생하면 해당 정보를 Control File
과 Data File Header
부분에 기록하게 됩니다.
Mini Checkpoint
Drop Table과 같이 특정한 DDL
발생 시 특정 블록에만 발생하는 Checkpoint입니다.
Recovery Checkpoint
Data File에 장애가 발생 했을 때 백업된 Data File을 복원한 후 Redo Change Vector를 적용시키게 됩니다. 그 후 Recovery된 블록을 Data File에 저장해야 하는데 이때 발생하는 Checkpoint가 Recovery Checkpoint
입니다.
Checkpoint Queue
: DB Buffer Cache에서 Data File로 내려 써야 할 Dirty Buffer들의 목록입니다. FIFO 구조로 되어 있습니다. 저장을 자주 하지 않게 되면(Checkpoint Queue의 길이가 길어지면) 성능은 좋아질 수 있지만 장애가 났을 경우 복구하는 시간이 길어지는 단점이 있고, 저장을 자주 하게 되면(Checkpoint Queue의 길이가 짧아지면) 반대가 됩니다.
참고:
<오라클 관리 실무> - 서진수