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 1Redo 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

by 짱구를꼭말려 2013. 9. 10. 17:29