글
Chap 6. Redo Log 관리하기
- Redo log buffer: 데이터의 변경이 생길 때 마다 장애를 대비해 변경되기 전과 후의 내용들 기록해 두는 메모리
- Redo log file: 데이터의 변경이 생길 때 마다 장애를 대비해 변경되기 전과 후의 내용들 기록해 두는 파일 (Redo log buffer 에서 내려쓰는 log 파일)
1. Redo Log 의 생성/기록 원리
사용자가 특정 데이터의 변경을 원하는 쿼리를 수행했다고 하면,
STEP 1)
서버 프로세스는 원하는 데이터 block 이 DB buffer cache 에 있는지 검사 한 후, 없으면 데이터 파일에서 원하는 데이터 block 을 복사해서 메모리 (DB buffer cache) 에 올려둔다.
이 때, DB buffer cache 의 해당 block 을 다른 사용자가 사용하지 못하게 lock 을 설정해 두어야 하는데 이 과정을 page fix 라고 한다.
또한, 변경되는 데이터의 모든 정보를 redo log 에 기록하기 위해 데이터 셋을 생성하는 데 이 데이터 셋을 Redo change Vector 이라고 한다. (PGA 에서 생성된다.)
STEP 2)
이렇게 PGA 상에서 만들어진 Change Vector 는 Redo log buffer 에 복사되는데, 서버 프로세스는 먼저 Redo log buffer 에 필요한 용량을 계산한다.
그리고 Redo log buffer 에 복사하기 위해 번호표의 역활을 하는 Latch (래치) 를 획득해야 하는데 (공유된 자원을 사용할 시 순서를 정리해 주는 역활) , 우선 Redo copy latch 를 먼저 확보 한 후 다시 Redo Allocation latch 를 확보해야 한다.
Oracle 8i 버전까지는 이 Redo Allocation latch 는 하나 밖에 없어서 데이터의 변경이 많이 되는 서버일 경우 이 latch 를 확보하느라 속도 저하가 있었을 수 있다. 그래서 9i 버전 부터는 Redo log buffer 를 여러개의 공간으로 나누어서 각 공간별 Redo Allocation latch 를 할당해 주는 Shared Redo Strand 라는 기능이 도입 되었다.
STEP 3)
이렇게 해서 Redo log buffer 에 저장된 데이터가 아래와 같은 상황이 되면 LGWR 에 의해 Redo log file 에 내려써지게 된다.
1) 3초 마다
2) Redo log buffer 의 전체 크기의 1/3 이 찼겨나 1M가 넘을 경우
3) 사용자가 commit / rollback 수행했을 때 (Transaction 이 종료 되었을 때)
4) DBWR 이 LGWR에게 쓰기를 요청할 때
위와 같은 경우가 발생해서 Redo log file 에 내려쓰고 내려 쓴 내용들은 Redo log buffer 에서 삭제 (Flush) 되면서 Redo log buffer 에 새로운 공간을 확보하게 된다.
2. Redo Log File 구성
1) Redo log file 의 구성
- Redo log file 은 group과 member라는 개념으로 관리 되는데, Oracle 7 버전 부터 장애에 대비해서 log file 을 여러 곳에 중복 저장하는 group이란 개념이 등장하였다.
- 아래는 Oracle Group 과 Member 의 최소 / 권장 갯수이다.
|
최 소 |
권 장 |
Group |
2 |
3 |
Member |
1 |
2 |
- 최소 Member 는 1개 이지만, 만약 이 Member 가 삭제 되든지 장애가 발생하면 이 Group 의 log data는 모두 손실 되기 때문에 2개의 Member 를 권장한다. 하지만 이 Member 가 더 많아 진다면 안정적일 수는 있지만, 기록시간이 늘어나니 서버에 부하를 줄 수 있다.
- 같은 group 의 member 의 크기는 모두 동일해야 한다.
- 또한, 같은 Group 의 Member 는 절대 동일한 디스크에 함께 두는 것을 권장하지 않는다. 만약의 경우 디스크에 장애가 날 경우, 그 Group 전체가 손상 될 수 있기 때문이다.
2) Redo log file 의 상태
상 태 |
의 미 |
Current |
현재 LGWR 이 사용중인 Redo log file (삭제 불가능) |
Inactive |
Redo log file 의 내용이 모두 DB 파일에 저장이 되어 있는 상태 (삭제 가능) |
Active |
Redo log file 의 내용이 아직 DB buffer cache 에서 Data file 로 저장이 안되어 있는 상태 (삭제 불가능) |
- current 에서 active 로 변경하는 방법: log switch 발생 (alter system switch logfile; )
- active 에서 inactive 로 변경하는 방법: checkpoint 발생 (alter system checkpoint; )
3) Log switch / SCN / Commit / Checkpoint
- Log Switch
위의 Redo log 의 생성 원리에서 봤듯이, LGWR 은 commit 이 발생 했을 경우, Redo log buffer 의 내용을 Redo log file 에 내려 쓰게 된다. 이렇게 내려 쓰다가 현재 쓰고 있는 log file 이 가득 차게 되면, 다음 log file 로 넘어가게 되는데, 이 과정을 Log Switch 라고 한다.
- SCN (System Commit Number)
Commit 이 발생 할때 Transaction 단위로 생성되는 고유 번호이다. 크게 SCN Base (4 bytes) + SCN Wrap(2 bytes) 로 구성되어 있다.
이 번호를 가지고 장애 발생 시 복구도 하게 된다.
- Commit
사용자가 commit 하게 되면 LGWR 이 해당 transaction 을 Redo Log File 에 기록하게 되는데, 이 때 4가지 방식이 있다.
** WAIT : 변경 된 Transaction 이 Redo log file 에 기록될 때 까지 기다린다.
** NOWAIT : WAIT 과 반대, Redo Log file 에 기록될 때 까지 기다리지 않는다.
** IMMEDIATE : Commit 요청이 들어오면 즉시 Redo Log file 에 기록한다.
** BATCH : Commit 요청이 들어오면 일정시간 동안 모아서 Redo log file 에 기록한다.
또한 commit 종류에는 동기식과 비동기식 commit 이 있는데,
** 동기식 commmit : 순서대로 작업하는 것. 즉, commit 을 수행 할 떄 LGWR 이 Redo Log buffer 의 내용을 Redo log file 에 기록을 완료한 후에 다음 작업을 한다. 이 방법은 안정성은 좋지만 성능 면에서 떨어진다.
** 비동기식 commit : 아직 Redo log file 에 기록이 완료되지 않아도 다른 작업을 할 수 있게 해서 성능을 높이는 방식이다. (NOWAIT)
- Checkpoint
Commit 된 데이터를 어디까지 저장했는지 확인하기 위해서 만들어 놓은 개념이다.
예를 들어, SCN 이 100번까지 commit 이 되었고, Checkpoint 정보가 90번 이라면 SCN 90 번 Transaction 까지는 데이터 파일에 저장이 되었다고 확인하는 것이다.
Checkpoint 에는 아래와 같은 종류가 있다.
** Database / Global Checkpoint : DB buffer cache 내에 있는 모든 저장 안된 Dirty buffer 들의 내용을 전부 데이터 파일로 저장하게 된다. 그리고 Checkpoint SCN (가장 큰 SCN 번호) 를 Control File 과 Data File Header 부분에 저장하게 된다.
** Thread Checkpoint / Logical Checkpoint : Log Switch 가 발생하면 생기는 Checkpoint 이다. 해당 Thread 내의 저장되지 않은 모든 Dirty Buffer 들을 Data file 로 전부 내려쓴다.
** Data file Checkpoint : 특정 데이터 파일에만 발생하는 Checkpoint 이다.
** Mini Checkpoint : Drop Table 같이 특정한 DDL 발생시 특정 블록에만 발생하는 checkpoint 이다.
** Recovery Checkpoint : 데이터 파일에 장애가 발생 했을 때 백업된 데이터 파일 복원 후 Redo Change Vector 를 적용시키고 recovery 된 블록을 데이터 파일에 저장해야 하는데 이떄 발생하는 checkpoint 이다.
- 위의 내용들의 더 자세한 설명을 위해 데이터 변경 작업을 예를 들어 보겠다.
- A 를 B 로, C 를 D 로 각각 순서대로 update 한다고 가정하자. 변경 순서는 아래와 같을 것이다.
STEP 1 - Redo Log buffer 에 A 에서 B 로 변경한다는 내용을 기록한다.
STEP 2 - Undo log 에 원본 데이터인 A 를 기록하고,
STEP 3 - 변경되는 값인 B 를 DB buffer Cache 에 올려둔다.
------------> 이 상태에서 commit 이 수행되면,
STEP 4 - LGWR 은 Redo Log File 에 Redo log buffer 에 있던 내용을 내려쓰고 (A->B 로 변경된다.), 다 내려쓰게 되면 commit 이 완료되면서 SCN (System Commit Number) 이 생성된다. (예를 들어, 1 번 이라 하자)
그리고 이 commit SCN 정보도 같이 redo log file 에 변경되는 데이터와 함께 저장된다. (commit SCN)
------------> 이 상태에서 현재 쓰고 있던 Redo log file 이 가득 차서 Log switch 가 발생하면,
STEP 5 - CKPT (Checkpoint Process) 가 DBWR 에게 checkpoint 신호를 전달해 주고, DBWR 은 DB buffer cache 에 있던 내용들을 (B 로 변경 된 내용) Data file 로 내려 쓰게 된다. 또한, checkpoint 가 발생할 때 마지막 SCN 정보를 (여기서는 현재 1 이다.) Control file 과 Data file header 에 기록하게 된다.
------------> 이 상태에서 C->D 로 update 하고 commit 을 했다고 하면,
STEP 6 - 앞의 step 1~ 4 까지 수행이 되면서, SCN 이 2 로 증가하고 (숫자는 예이다..) 업데이트 된 D 라는 데이터와 SCN 정보가 Redo log file 에 기록 될 것이다.
즉, 현재까지는 Control file 과 Data file 의 SCN 은 1 이고, Redo log file 의 SCN 은 2이다. (아직 서로 다르다.)
------------> 만약, 이 상태에서 checkpoint 가 발생하기 전에 서버가 장애가 나서 종료되면?
STEP 7 - 서버를 다시 startup 할 때 Instance recovery 를 하게 될 텐데, 이 때 Oracle 은 Control file 에 있는 SCN 정보와 Redo log file 에 있는 SCN 정보를 비교할 것이다. 만약 이 정보가 다르다면, Oracle 은 문제가 있다고 판단하여 복구를 시작하게 된다.
3. Redo log file 관리
1) 현재 로그 상태 확인하기
set line 200
col group# for 999
col mb for 9999
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", b.first_change# from v$logfile a, v$log b where a.group#=b.group# order by 1,2;
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- -------------
1 /app/oracle/oradata/testdb/redo01.log 50 4 INACTIVE NO 821963
2 /app/oracle/oradata/testdb/redo02.log 50 5 CURRENT NO 841347
3 /app/oracle/oradata/testdb/redo03.log 50 3 INACTIVE NO 809784
2) 신규 group 생성 및 member 추가
- 현재 group 3 까지 있으므로 4번을 생성해 본다
SQL> alter database add logfile group 4 '/app/oracle/oradata/testdb/redo04_a.log' size 5M;
Database altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- -------------
1 /app/oracle/oradata/testdb/redo01.log 50 4 INACTIVE NO 821963
2 /app/oracle/oradata/testdb/redo02.log 50 5 CURRENT NO 841347
3 /app/oracle/oradata/testdb/redo03.log 50 3 INACTIVE NO 809784
4 /app/oracle/oradata/testdb/redo04_a.log 5 0 UNUSED YES 0
SQL> alter database add logfile member '/app/oracle/oradata/testdb/redo04_b.log' to group 4;
Database altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- -------------
1 /app/oracle/oradata/testdb/redo01.log 50 4 INACTIVE NO 821963
2 /app/oracle/oradata/testdb/redo02.log 50 5 CURRENT NO 841347
3 /app/oracle/oradata/testdb/redo03.log 50 3 INACTIVE NO 809784
4 /app/oracle/oradata/testdb/redo04_a.log 5 0 UNUSED YES 0
4 /app/oracle/oradata/testdb/redo04_b.log 5 0 UNUSED YES 0
3) log switch 와 checkpoint 를 발생시켜 본다
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- -------------
1 /app/oracle/oradata/testdb/redo01.log 50 4 INACTIVE NO 821963
2 /app/oracle/oradata/testdb/redo02.log 50 5 CURRENT NO 841347
3 /app/oracle/oradata/testdb/redo03.log 50 3 INACTIVE NO 809784
4 /app/oracle/oradata/testdb/redo04_a.log 5 0 UNUSED YES 0
4 /app/oracle/oradata/testdb/redo04_b.log 5 0 UNUSED YES 0
-- 현재 current log 는 2번 group 이다.
SQL> alter system switch logfile;
System altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- -------------
1 /app/oracle/oradata/testdb/redo01.log 50 4 INACTIVE NO 821963
2 /app/oracle/oradata/testdb/redo02.log 50 5 ACTIVE NO 841347
3 /app/oracle/oradata/testdb/redo03.log 50 3 INACTIVE NO 809784
4 /app/oracle/oradata/testdb/redo04_a.log 5 6 CURRENT NO 848254
4 /app/oracle/oradata/testdb/redo04_b.log 5 6 CURRENT NO 848254
-- log switch 가 일어나자 current group 이였던 2번이 active 로 변했고,
-- 새로 생성한 4번 group 이 current 가 되었다.
SQL> alter system checkpoint;
System altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- -------------
1 /app/oracle/oradata/testdb/redo01.log 50 4 INACTIVE NO 821963
2 /app/oracle/oradata/testdb/redo02.log 50 5 INACTIVE NO 841347
3 /app/oracle/oradata/testdb/redo03.log 50 3 INACTIVE NO 809784
4 /app/oracle/oradata/testdb/redo04_a.log 5 6 CURRENT NO 848254
4 /app/oracle/oradata/testdb/redo04_b.log 5 6 CURRENT NO 848254
-- checkpoint 가 일어나자 active 였던 2번 group 이 inactive 가 되었다.
4) 기존 member 및 group 삭제
- 신규로 만들었던 group 4번을 삭제해 보자.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- ------------- 1 /app/oracle/oradata/testdb/redo01.log 50 8 INACTIVE NO 848575 2 /app/oracle/oradata/testdb/redo02.log 50 9 INACTIVE NO 848580 3 /app/oracle/oradata/testdb/redo03.log 50 7 INACTIVE NO 848562 4 /app/oracle/oradata/testdb/redo04_a.log 5 10 CURRENT NO 848587 4 /app/oracle/oradata/testdb/redo04_b.log 5 10 CURRENT NO 848587
SQL> alter database drop logfile group 4;
alter database drop logfile group 4
* ERROR at line 1:
ORA-01623: log 4 is current log for instance testdb (thread 1) - cannot drop
ORA-00312: online log 4 thread 1: '/app/oracle/oradata/testdb/redo04_a.log'
ORA-00312: online log 4 thread 1: '/app/oracle/oradata/testdb/redo04_b.log'
------------------------------------------------------------------------
-- 위의 에러는 보면 current log 이기 때문에 삭제가 안된다.
-- 위에서 current와 active log는 삭제가 안된다고 하였다.
-- 그러므로 inactive 상태로 만들어 주어야 한다.
------------------------------------------------------------------------
SQL> alter system switch logfile;
System altered.
SQL> @log GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE# ------ --------------------------------------------- ----- ---- -------- ----- ------------- 1 /app/oracle/oradata/testdb/redo01.log 50 8 INACTIVE NO 848575 2 /app/oracle/oradata/testdb/redo02.log 50 9 INACTIVE NO 848580 3 /app/oracle/oradata/testdb/redo03.log 50 11 CURRENT NO 848665 4 /app/oracle/oradata/testdb/redo04_a.log 5 10 ACTIVE NO 848587 4 /app/oracle/oradata/testdb/redo04_b.log 5 10 ACTIVE NO 848587 SQL> alter system checkpoint; System altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- ------------- 1 /app/oracle/oradata/testdb/redo01.log 50 8 INACTIVE NO 848575 2 /app/oracle/oradata/testdb/redo02.log 50 9 INACTIVE NO 848580 3 /app/oracle/oradata/testdb/redo03.log 50 11 CURRENT NO 848665 4 /app/oracle/oradata/testdb/redo04_a.log 5 10 INACTIVE NO 848587 4 /app/oracle/oradata/testdb/redo04_b.log 5 10 INACTIVE NO 848587
------------------------------------------------------------------------
-- 이제 group 4번이 inactive 가 되었다. 우선 member 부터 삭제해 본다
------------------------------------------------------------------------
SQL> alter database drop logfile member '/app/oracle/oradata/testdb/redo04_b.log';
Database altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- ------------- 1 /app/oracle/oradata/testdb/redo01.log 50 8 INACTIVE NO 848575 2 /app/oracle/oradata/testdb/redo02.log 50 9 INACTIVE NO 848580 3 /app/oracle/oradata/testdb/redo03.log 50 11 CURRENT NO 848665 4 /app/oracle/oradata/testdb/redo04_a.log 5 10 INACTIVE NO 848587
SQL> alter database drop logfile member '/app/oracle/oradata/testdb/redo04_a.log';
alter database drop logfile member '/app/oracle/oradata/testdb/redo04_a.log'
*
ERROR at line 1:
ORA-00361: cannot remove last log member /app/oracle/oradata/testdb/redo04_a.log for group 4
------------------------------------------------------------------------
-- 위의 에러가 나는 이유는, 하나의 group 에는 최소 하나의 member 가 존재해야 하기 때문이다.
-- 이럴경우, 전체 group 를 지워주면 된다.
------------------------------------------------------------------------
SQL> alter database drop logfile group 4;
Database altered.
SQL> @log
GROUP# MEMBER MB SEQ# STATUS ARC FIRST_CHANGE#
------ --------------------------------------------- ----- ---- -------- ----- ------------- 1 /app/oracle/oradata/testdb/redo01.log 50 8 INACTIVE NO 848575 2 /app/oracle/oradata/testdb/redo02.log 50 9 INACTIVE NO 848580 3 /app/oracle/oradata/testdb/redo03.log 50 11 CURRENT NO 848665
'Oracle > Admin' 카테고리의 다른 글
[Oracle Admin] Chap 8. Oracle 저장구조 (0) | 2013.09.14 |
---|---|
[Oracle Admin] Chap 7. Tablespace 와 Data file 관리하기 (0) | 2013.09.11 |
[Oracle Admin] Chap 5. Control File 관리하기 (0) | 2013.09.09 |
[Oracle Admin] Chap 4. Oracle 시작하기와 종료하기 (0) | 2013.09.08 |
[Oracle Admin] Chap 3. Oracle background process (0) | 2013.09.08 |