Redo Log 스위치 발생량 관리 및 설정 방법

안녕하세요, Surmin입니다.

이번에는 redo log 관련 테스트 내용을 가져왔습니다. 참고하시면 좋을 것 같습니다. 감사합니다!

오라클 권고 사항

It may not always be possible to provide a specific size recommendation for redo log files, but redo log files in the range of a hundred megabytes to a few gigabytes are considered reasonable. Size your online redo log files according to the amount of redo your system generates. A rough guide is to switch logs at most once every twenty minutes.” ⇒ 20분에 1번

결론: 시간당 Log switch 발생 3회 이하 / 하루(24시간) = 72회 이하

실습

  • 날짜별로 Log switch 확인
    • ALTER SYSTEM SWITCH LOGFILE; → COUNT 됨.
    • ALTER SYSTEM CHECKPOINT; → COUNT 안됨.
#오늘 날짜를 기준으로 30일 확인 
SQL> set line 200 pages 1000

SELECT TO_CHAR(FIRST_TIME,'YY/MM/DD HH24') HOUR, COUNT(*) CNT
FROM  V$LOGHIST
WHERE FIRST_TIME >= TRUNC(SYSDATE - 30)
GROUP BY TO_CHAR(FIRST_TIME,'YY/MM/DD HH24')
ORDER BY 1;

HOUR       |       CNT
-----------|----------
24/12/08 23|         1
24/12/14 21|         1
24/12/16 21|         1
24/12/17 01|         1
24/12/17 23|         2
24/12/18 02|         1
24/12/19 00|         1
24/12/19 22|         1
24/12/20 23|         1
24/12/21 18|         1
24/12/23 01|         1
24/12/28 23|         1
24/12/30 00|         1
25/01/01 18|         1
25/01/01 20|         1
25/01/05 23|         3

16 rows selected.

#전체 Log switch 발생 날짜 및 횟수 확인 
SELECT TO_CHAR(first_time,'YYYY-MM-DD HH24:MI:SS') first_time,
       THREAD#, SEQUENCE#
FROM v$log_history
ORDER BY first_time DESC;
FIRST_TIME         |   THREAD#| SEQUENCE#
-------------------|----------|----------
2025-01-05 23:15:08|         1|        38
2025-01-05 23:14:31|         1|        37
2025-01-05 23:13:12|         1|        36
2025-01-01 20:19:57|         1|        35
2025-01-01 18:40:12|         1|        34
2024-12-30 00:37:52|         1|        33
2024-12-28 23:07:43|         1|        32
....
  • 특정 날짜만 보고싶은 경우는?
SELECT TO_CHAR(first_time,'YYYY-MM-DD HH24:MI:SS') first_time,
       THREAD#, SEQUENCE#
FROM v$log_history
WHERE TO_CHAR(first_time, 'YYYY-MM-DD') = '2025-01-05'
ORDER BY first_time DESC;

FIRST_TIME         |   THREAD#| SEQUENCE#
-------------------|----------|----------
2025-01-05 23:15:08|         1|        38
2025-01-05 23:14:31|         1|        37
2025-01-05 23:13:12|         1|        36
  • 특정 날짜 와 시간대 범위로 보고싶은 경우는?
SELECT TO_CHAR(first_time, 'HH24') || ':00-' ||
       TO_CHAR(first_time, 'HH24') || ':59' as "Time Range",
       COUNT(*) as "Switch Count",
       MIN(TO_CHAR(first_time, 'HH24:MI:SS')) as "First Switch",
       MAX(TO_CHAR(first_time, 'HH24:MI:SS')) as "Last Switch"
FROM v$log_history
WHERE TRUNC(first_time) = TO_DATE('2024-07-29', 'YYYY-MM-DD')
GROUP BY TO_CHAR(first_time, 'HH24')
ORDER BY "Time Range";

Time Range |Switch Count|First Sw|Last Swi
-----------|------------|--------|--------
13:00-13:59|           1|13:57:57|13:57:57
14:00-14:59|           4|14:04:50|14:09:36
16:00-16:59|          20|16:15:28|16:56:26

redo resize의 기준은?

  • 먼저 설명을 위해 Log switch 여러번 발생 시킵니다.
SQL> alter system switch logfile;
  • Test한 날짜로 확인
SELECT TO_CHAR(first_time, 'HH24') || ':00-' ||
       TO_CHAR(first_time, 'HH24') || ':59' as "Time Range",
       COUNT(*) as "Switch Count",
       MIN(TO_CHAR(first_time, 'HH24:MI:SS')) as "First Switch",
       MAX(TO_CHAR(first_time, 'HH24:MI:SS')) as "Last Switch"
FROM v$log_history
WHERE TRUNC(first_time) = TO_DATE('2025-01-05', 'YYYY-MM-DD')
GROUP BY TO_CHAR(first_time, 'HH24')
ORDER BY "Time Range";

Time Range |Switch Count|First Sw|Last Swi
-----------|------------|--------|--------
23:00-23:59|          32|23:13:12|23:58:45

32번의 로그 스위치가 발생한 것을 확인하였습니다. 오라클에서 권장하는 기준은 20분에 1번, 즉 1시간에 3번입니다. 이를 기준으로 할 때, 현재 발생 빈도는 약 10배에 달하는 것으로 나타났습니다. 따라서 현재 redo size를 10배로 늘려주기로 하였습니다.

  • 먼저 redo size 확인 및 상태를 확인 확입니다.
    • 확인 시 맴버가 같이 있는 것을 확인
    • 용량은 200M 확인 ⇒ 2G 늘립니다.
    • GROUP 2은 CURRENT 상태이니 마지막에 진행.
SELECT a.group#,
       b.sequence#,
       a.member,
       b.bytes/1024/1024 as "Size(MB)",
       b.archived,
       b.status,
       b.first_time,
       b.next_time,
       b.first_change# as first_scn,
       b.next_change# as next_scn
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY a.group#, b.sequence#;

    GROUP#| SEQUENCE#|MEMBER                                            |  Size(MB)|ARC|STATUS    |FIRST_TIME          |NEXT_TIME           | FIRST_SCN|  NEXT_SCN
----------|----------|--------------------------------------------------|----------|---|----------|--------------------|--------------------|----------|----------
         1|        67|/u01/app/oracle/oradata/ORA19C/redo01.log         |       200|YES|INACTIVE  |05-JAN-25           |05-JAN-25           |   9397476|   9397523
         1|        67|/u01/app/oracle/fast_recovery_area/ORA19C/onlinelo|       200|YES|INACTIVE  |05-JAN-25           |05-JAN-25           |   9397476|   9397523
          |          |g/redo01.log                                      |          |   |          |                    |                    |          |

         2|        68|/u01/app/oracle/fast_recovery_area/ORA19C/onlinelo|       200|NO |CURRENT   |05-JAN-25           |                    |   9397523|##########
          |          |g/redo02.log                                      |          |   |          |                    |                    |          |

         2|        68|/u01/app/oracle/oradata/ORA19C/redo02.log         |       200|NO |CURRENT   |05-JAN-25           |                    |   9397523|##########
         3|        66|/u01/app/oracle/fast_recovery_area/ORA19C/onlinelo|       200|YES|INACTIVE  |05-JAN-25           |05-JAN-25           |   9397463|   9397476
          |          |g/redo03.log                                      |          |   |          |                    |                    |          |

         3|        66|/u01/app/oracle/oradata/ORA19C/redo03.log         |       200|YES|INACTIVE  |05-JAN-25           |05-JAN-25           |   9397463|   9397476

6 rows selected.
  • resize 합니다.
    • 물리적으로도 리두로그 파일을 삭제 해줍니다.
    • 맴버인 경우는 용량이 2배로 듭니다.
ALTER DATABASE DROP LOGFILE GROUP 1;

#아래와 같은 식으로 경로 찾아서 삭제 합니다. 
[oracle@oracle19c ORA19C]$ rm -r redo01.log
[oracle@oracle19c onlinelog]$ rm -r redo01.log    

ALTER DATABASE 
  ADD LOGFILE GROUP 1 
  ('/u01/app/oracle/oradata/ORA19C/redo01.log',
   '/u01/app/oracle/fast_recovery_area/ORA19C/onlinelog/redo01.log')
  SIZE 2G;

ALTER DATABASE DROP LOGFILE GROUP 3;

[oracle@oracle19c ORA19C]$ rm -r redo03.log
[oracle@oracle19c onlinelog]$ rm -r redo03.log   

ALTER DATABASE 
  ADD LOGFILE GROUP 3 
  ('/u01/app/oracle/oradata/ORA19C/redo03.log',
   '/u01/app/oracle/fast_recovery_area/ORA19C/onlinelog/redo03.log')
  SIZE 2G;

# CURRENT 상태이니 강제로 로그 스위치 발생 시킵니다.   
# 오래걸리면 **ALTER SYSTEM CHECKPOINT;  합니다**
ALTER SYSTEM SWITCH LOGFILE;

ALTER DATABASE DROP LOGFILE GROUP 2;

[oracle@oracle19c ORA19C]$ rm -r redo02.log
[oracle@oracle19c onlinelog]$ rm -r redo02.log    

ALTER DATABASE 
  ADD LOGFILE GROUP 2 
  ('/u01/app/oracle/oradata/ORA19C/redo02.log',
   '/u01/app/oracle/fast_recovery_area/ORA19C/onlinelog/redo02.log')
  SIZE 2G;

===
#만약 맴버가 없다고 가정하였을때 추가하고 싶다면?
ALTER DATABASE ADD LOGFILE MEMBER
'/u01/app/oracle/fast_recovery_area/ORA19C/onlinelog/redo01.log' TO GROUP 1,
'/u01/app/oracle/fast_recovery_area/ORA19C/onlinelog/redo02.log' TO GROUP 2,
'/u01/app/oracle/fast_recovery_area/ORA19C/onlinelog/redo03.log' TO GROUP 3;
#만들어진거확인   (select * from v$log; 명령어로는 안보임 맴버들)
select * from v$logfile;

#만약 맴버만 빼고 리사이즈 하고 싶다면?
ALTER DATABASE ADD LOGFILE GROUP 1 ('/u01/app/oracle/oradata/ORA19C/redo01.log') SIZE 2G;
===
  • 작업 완료 후 확인
SELECT a.group#,
       b.sequence#,
       a.member,
       b.bytes/1024/1024 as "Size(MB)",
       b.archived,
       b.status,
       b.first_time,
       b.next_time,
       b.first_change# as first_scn,
       b.next_change# as next_scn
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY a.group#, b.sequence#;      

    GROUP#| SEQUENCE#|MEMBER                                            |  Size(MB)|ARC|STATUS    |FIRST_TIME          |NEXT_TIME           | FIRST_SCN|  NEXT_SCN
----------|----------|--------------------------------------------------|----------|---|----------|--------------------|--------------------|----------|----------
         1|        69|/u01/app/oracle/oradata/ORA19C/redo01.log         |      2048|YES|INACTIVE  |06-JAN-25           |06-JAN-25           |   9405322|   9405542
         1|        69|/u01/app/oracle/fast_recovery_area/ORA19C/onlinelo|      2048|YES|INACTIVE  |06-JAN-25           |06-JAN-25           |   9405322|   9405542
          |          |g/redo01.log                                      |          |   |          |                    |                    |          |

         2|         0|/u01/app/oracle/fast_recovery_area/ORA19C/onlinelo|      2048|YES|UNUSED    |                    |                    |         0|         0
          |          |g/redo02.log                                      |          |   |          |                    |                    |          |

         2|         0|/u01/app/oracle/oradata/ORA19C/redo02.log         |      2048|YES|UNUSED    |                    |                    |         0|         0
         3|        70|/u01/app/oracle/fast_recovery_area/ORA19C/onlinelo|      2048|NO |CURRENT   |06-JAN-25           |                    |   9405542|##########
          |          |g/redo03.log                                      |          |   |          |                    |                    |          |

         3|        70|/u01/app/oracle/oradata/ORA19C/redo03.log         |      2048|NO |CURRENT   |06-JAN-25           |                    |   9405542|##########

6 rows selected.
  • redo 파일 resize 후 백업을 다시 해야 나요??
    • db복구시 사용하는 resetlogs 라는 명령이 그 sequence 를 초기화하는 역할을 하고 새 incarnation(인카네이션) 으로 db 를 기동 시키는 것임으로 새로운 백업을 받아야 하지만 단순 리두로그 크기증가나 감소 작업으로 리두를 삭제하는 경우에는 다시 백업 받을 필요 없습니다.

아카이브 로그 확인 및 용량

  • ex) redo log file size 200M * 10 번 발생을 할경우 아카이브 로그는 2G 다
    • 정상적인 경우에는 redo log 사이즈와 비례하겠지만, 강제로 로그 스위치를 발생시킬 경우의 용량은 ?
#redo size 확인 
SELECT a.group#,
       b.sequence#,
       a.member,
       b.bytes/1024/1024 as "Size(MB)",
       b.archived,
       b.status,
       b.first_time,
       b.next_time,
       b.first_change# as first_scn,
       b.next_change# as next_scn
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY a.group#, b.sequence#;

    GROUP#| SEQUENCE#
----------|----------
MEMBER
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  Size(MB)|ARC|STATUS    |FIRST_TIME         |NEXT_TIME          | FIRST_SCN|  NEXT_SCN
----------|---|----------|-------------------|-------------------|----------|----------
         1|         0
/u01/app/oracle/oradata/ORA19C/redo01.log
       200|YES|UNUSED    |                   |                   |         0|         0

         2|        74
/u01/app/oracle/oradata/ORA19C/redo02.log
       200|YES|INACTIVE  |2025-01-08 15:28:41|2025-01-09 11:02:33|   7805718|   7918742

         3|        75
/u01/app/oracle/oradata/ORA19C/redo03.log
       200|NO |CURRENT   |2025-01-09 11:02:33|                   |   7918742|1.8447E+19

#강제로 로그 스위치 방생
SQL> ALTER SYSTEM SWITCH LOGFILE;

#10번 발생 하였는지 확인
SQL> SELECT TO_CHAR(FIRST_TIME,'YY/MM/DD HH24') HOUR, COUNT(*) CNT
FROM  V$LOGHIST
WHERE FIRST_TIME >= TRUNC(SYSDATE - 30)
GROUP BY TO_CHAR(FIRST_TIME,'YY/MM/DD HH24')
ORDER BY 1;

HOUR       |       CNT
-----------|----------
....
25/01/09 13|        10
  • 아카이브(ARCHIVE) 용량을 확인해봅니다.
    • 용량이 한참 적다는 것을 확인 하였습니다.
    • 해당 명령어를 통해 강제적으로 스위치를 발생시켰을 가능성도 유추할 수 있습니다.
select CTIME, round(TOT/1024/1024,2) MB
from (select to_char(completion_time, 'YYYYMMDD') ctime,
      sum(blocks*block_size) TOT
      from v$archived_log
      group by  to_char(completion_time, 'YYYYMMDD')
      order by ctime);

CTIME   |        MB
--------|----------
....
20250109|    127.79  

17 rows selected.
위로 스크롤