블로그 이미지
redkite

카테고리

분류 전체보기 (291)
00.SI프로젝트 산출물 (0)
00.센터 운영 문서 (0)
01.DBMS ============.. (0)
01.오라클 (117)
01.MS-SQL (15)
01.MySQL (30)
01.PostgreSql (0)
01.DB튜닝 (28)
====================.. (0)
02.SERVER ==========.. (0)
02.서버-공통 (11)
02.서버-Linux (58)
02.서버-Unix (12)
02.서버-Windows (2)
====================.. (0)
03.APPLICATION =====.. (11)
====================.. (0)
04.ETC =============.. (0)
04.보안 (5)
====================.. (0)
05.개인자료 (1)
06.캠핑관련 (0)
07.OA관련 (1)
Total
Today
Yesterday

달력

« » 2024.5
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

공지사항

최근에 올라온 글

'01.오라클'에 해당되는 글 117건

  1. 2012.12.19 [오라클]백업 복구 가이드 - 노아카이브와 아카이브 모드
  2. 2012.12.19 [오라클]백업 복구 가이드 - ON-Line 백업을 이용한 장애 복구
  3. 2012.12.19 [오라클]백업 복구 가이드 - OFF-Line 백업을 이용한 불완전 백업
  4. 2012.12.19 [오라클]백업 복구 가이드 - OFF-Line 백업을 이용한 완전 백업
  5. 2012.12.19 [오라클]물리적 백업 / 논리적 백업
  6. 2012.12.19 [오라클]Redo Log Resize 방법
  7. 2012.12.19 [오라클]Undo Tablespace 변경
  8. 2012.12.19 [오라클]테이블스페이스 생성 및 관리
  9. 2012.12.19 [오라클]Data Type - DECODE 함수와 ORA-01722
  10. 2012.12.19 [오라클]PK컬럼 순서와 데이터베이스 성능
  11. 2012.12.19 [오라클]설치 시 커널 매개변수 설정
  12. 2012.12.19 [오라클]Plan Table is Old Version
  13. 2012.12.19 [오라클]IMP-00017 에러 처리 방법
  14. 2012.12.19 [오라클]ORA-01536 해결하기
  15. 2012.12.19 [오라클]Lock Object 확인
  16. 2012.12.19 [오라클]ORA-0925 해결하기
  17. 2012.12.19 [오라클]Undo Segment 삭제 방법
  18. 2012.12.19 [오라클]DBMS STAT PACK 이용
  19. 2012.12.19 [오라클]통계정보 갱신 방법
  20. 2012.12.19 [오라클]INDEX 생성 가이드라인
  21. 2012.12.19 [오라클] Oracle 8i Nosegment Index vs. Oracle 11g Invisible Index
  22. 2012.12.19 [오라클]데이터 베이스 아키텍쳐
  23. 2012.12.19 [오라클]데이터 파일 최대 지원 수
  24. 2012.12.19 [오라클]JDBC와 JDK 대응 버젼
  25. 2012.12.19 [오라클]RAC 기본 명령어
  26. 2012.12.19 [오라클]ROWNUM 쿼리 분석
  27. 2012.12.19 [오라클]파티션 테이블 생성
  28. 2012.12.19 [오라클]Standby DBMS 구성
  29. 2012.12.19 [오라클]11g 테이블스페이스 Alter 옵션
  30. 2012.12.19 [오라클]INDEX 값에 대한 설명

백업과 복구 원리에서 알아보았듯이 사용자의 모든 변경 정보는 기본적으로 로그버퍼 영역과 리두로그 파일에 저장되어 데이터베이스 복구 시 사용됩니다. 이러한 환경을 노-아카이브 모드라고 하며 오라클 데이터베이스를 설치하면 기본적으로 노-아카이브 모드로 설정됩니다. 이 모드는 사용자의 모든 변경정보가 리두로그 파일에 백업되기 때문에 리두로그 파일의 크기와 개수가 백업할 수 있는 데이터의 크기를 좌우하게 됩니다. 결론적으로 데이터베이스를 복구해야 할 때 리두로그 파일이 아주 오래 전의 복구 데이터를 가지고 있지 않다면 복구를 할 수 없는 단점을 가지고 있습니다.

 

3장 노-아카이브와 아카이브 모드

  3-1 백업과 복구의 종류

오라클 데이터베이스에는 4 가지 백업 방법과 8 가지 복구 방법이 제공됩니다.

백업 방법은 다시 두 가지 방법으로 실행할 수 있는데, 첫 번째, 물리적 방법(PHYSICAL MODE)은 오라클 데아터베이스와 관련된 모든 파일들(데이터 파일, 컨트롤 파일, 리두로그 파일, 파라메터 파일)을 운영체계에서 제공하는 복사 명령어(도스-COPY,UNIX-cp, cpio, ufsdump 등)로 다른 물리적 장치에 복사하는 방법을 의미합니다.

두 번째 논리적 방법(LOGICAL MODE)은 오라클 사에서 제공하는 EXPORT 유틸리티를 통해 데이터베이스 내의 테이블, 뷰, 인덱스, PL/SQL 블록 등을 운영체제 상의 파일형태로 복사하는 방법을 의미합니다.

다음은 복구방법 입니다. 복구 방법도 두 가지 모드에서 실행할 수 있습니다. 첫 번째 방법은 노-아키이브 모드(NOARCHIVE MODE))입니다. 백업과 복구 원리에서 알아보았듯이 사용자의 모든 변경 정보는 기본적으로 로그버퍼 영역과 리두로그 파일에 저장되어 데이터베이스 복구 시 사용됩니다. 이러한 환경을 노-아카이브 모드라고 하며 오라클 데이터베이스를 설치하면 기본적으로 노-아카이브 모드로 설정됩니다. 이 모드는 사용자의 모든 변경정보가 리두로그 파일에 백업되기 때문에 리두로그 파일의 크기와 개수가 백업할 수 있는 데이터의 크기를 좌우하게 됩니다. 결론적으로 데이터베이스를 복구해야 할 때 리두로그 파일이 아주 오래 전의 복구 데이터를 가지고 있지 않다면 복구를 할 수 없는 단점을 가지고 있습니다.

두 번째 방법은 아카이브 모드(ARCHIVE MODE)입니다. 이 모드에는 완전복구(COMPLETE RECOVERY)와 불완전 복구(INCOMPLETE RECOVERY) 방법이 있습니다. 모든 복구 데이터를 가지고 있으며 데이터베이스에 문제가 발생했던 시점까지 복구할 수 있는데 이러한 방법을 완전복구(Complete Recovery)라고 하며, 반대로, 복구할 수 있는 데이터가 백업되어 있지 않다면 문제가 생겼던 시점까지 복구할 수 없는데 이러한 방법을 불완전 복구(In-Complete Recovery)라고 합니다. 사용자들은 이러한 다양한 백업과 복구방법을 통해 데이터베이스의 가용성을 높일 수 있습니다.

자~ 그럼 노-아카이브 모드와 아카이브 모드에 대해 자세히 알아 보도록 하겠습니다.


  3-2 노-아카이브 모드

오라클 서버는 사용자들이 입력, 수정, 삭제작업을 수행할 때 마다 발생하는 모든 변경 전 데이터와 변경 후 데이터들을 리두로그 버퍼 영역에 백업하게 됩니다. 이어, LGWR 백그라운드 프로세스는 리두로그 버퍼의 데이터들을 영구히 저장할 수 있는 리두로그 파일로 저장하게 됩니다. 이것이, 오라클 서버가 제공하는 백업 메커니즘입니다.

그런데, 기본적으로 오라클 데이터베이스를 설치하면 3개의 리두로그 파일이 제공됩니다.

최초, LGWR 프로세스는 첫번째 리두로그 파일에 데이터를 저장하며, 이 파일이 모두 사용되면, 두 번째 리두로그 파일로 이동하여 계속적으로 데이터를 저장하게 됩니다. 
두 번째 리두로그 파일도 모두 저장되고 나면 세 번째 리두로그 파일에 쓰기 작업을 계속하게 됩니다. 그런데, 세 번째 리두로그 파일도 모두 사용되고 나면, 더 이상 제공되는 리두로그 파일이 없기 때문에 다시 첫 번째 리두로그 파일에 백업 데이터들을 저장하게 됩니다. 
이때, 이전에 저장되어 있는 백업 데이터 위에 새로운 백업 데이터들을 저장하기 때문에 이전 백업 데이터들은 모두 유실되는 문제가 발생하게 됩니다.

이미 소개 드린 대로 리두로그 파일의 용도는 오라클 데이터베이스에 장애가 발생하는 경우 백업된 리두로그 파일의 데이터들을 통해 데이터베이스를 복구하기 위한 용도라고 배웠습니다. 그런데, 위 그림처럼, 백업될 충분한 공간이 확보되지 못한 경우에는 결국 이전에 사용된 리두로그 파일을 재사용할 수 밖에 없게 되는 문제가 발생하게 됩니다.

오라클 데이터베이스에서는 이러한 환경을 노-아카이브 모드(No-Archive Mode)라고 하며 기본적으로 오라클 데이터베이스 설치하면 노-아카이브 모드가 기본 환경입니다.

다음은 사용 중인 데이터베이스의 아카이브 모드 상태를 확인하는 방법입니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> CONNECT /AS SYSDBA SQL> ARCHIVE LOG LIST Database log mode No Archive Mode ← 노-아카이브 모드 Automatic archival Disabled Archive destination C:\oracle\ora92\database\arch Oldest online log sequence 51 Current log sequence 53

이 결과를 참조했을 때 "Database log mode"의 결과가 "No Archive Mode"임을 확인할 수 있습니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> SET LINESIZE 1000 SQL> SELECT GROUP#, SEQUENCE#, ARCHIVED, STATUS FROM V$LOG; GROUP# SEQUENCE# ARC STATUS ---------- ---------- ---- ----------- 1 52 NO INACTIVE 2 53 NO CURRENT 3 51 NO INACTIVE

이 결과를 참조했을 때 ARC 컬럼의 값이 "NO"는 노-아키이브 모드라는 것을 의미합니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp> SQL> SELECT ARCHIVER FROM V$INSTANCE; ARCHIVE ------- STOPPED

이 결과를 참조했을 때 "STOPPED"는 노-아키이브 모드라는 것을 의미합니다.


  3-3 오프라인 백업

오라클 사에서 제공하는 백업방법 중에 가장 대표적인 방법이며 또한 가장 쉽고 간단하게 수행할 수 있는 방법입니다. 하지만, 경우에 따라서는 가장 수행하기 어려운 방법 중에 하나이기도 합니다.

오프라인 백업 방법은 버전에 따라 콜드백업(Cold Backup), 전체백업(Whole Backup)이라고도 부르며 다음과 같은 주요 특징이 있습니다.

1) 반드시, 오라클 서버를 종료(Shutdown) 해야 합니다. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> SHUTDOWN SQL> EXIT

여기서, 한가지 주의해야 할 점은 오라클 서버를 종료할 때 반드시 정상적인 종료 옵션(NORMAL, TRANSACTIONAL, IMMEDIATE)을 사용하셔야 합니다. 만약, ABORT와 같은 비정상적인 옵션을 사용하여 데이터베이스를 종료한 후 백업작업을 수행한다면, 이 백업 데이터는 장애 발생 시 사용하지 못하게 됩니다. 즉, 데이터베이스를 복구할 수 없게 되는 치명적인 난관에 부딪히게 됩니다. 그 이유는 간단합니다. ABORT 옵션의 의미는 현재 오라클 서버에 할당된 메모리 공간을 즉시 종료하고 사용 중이던 모든 파일의 상태를 비정상적인 상태로 남긴 후 데이터베이스를 종료 시키기 때문입니다. 예를 들어, WINDOWS 환경에서 어떤 작업을 수행하다가 시스템을 종료해야 한다면 [시작] 버튼을 클릭한 후 [시스템 종료]를 선택합니다. 이것은 정상적인 방법으로 시스템을 종료하는 방법이지요.

하지만, 때로는, 갑작스런 정전으로 인해 미처 정상적인 방법으로 시스템을 종료하지 못하는 경우도 있게 마련입니다. 이런 경우, 다시 시스템을 부팅하게 되면 운영체계는 시스템을 복구모드로 전환하여 갑작스런 다운 시 정상적인 종료를 하지 못한 파일들을 정상적으로 종료 시킨 후 다시 오픈 시켜주는 작업을 수행하게 됩니다.

오라클 데이터베이스 환경에서 SHUTDOWN ABORT 옵션의 의미는 바로 갑작스런 정전으로 인해 데이터베이스가 비정상적으로 종료된 경우와 동일한 상태를 의미하게 됩니다.

결론적으로, 이런 경우, 데이터베이스를 다시 재 시작(Startup)하게 되면 오라클 서버는 내부적으로 복구 작업을 수행하게 됩니다. 이때 , 복구작업을 수행하는 백그라운드 프로세는 SMON(System Monitor) 입니다.

사용자의 순간적인 실수로 백업된 모든 데이터들이 사용되지 못하는 경우가 실제 기업 환경에서 종종 볼 수 있습니다. 이러한 백업 작업을 안전하게 수행할 때는 2번 ~ 3번 확인하신 후 절차에 의해 작업 하셔야 합니다.


2) 오라클 데이터베이스와 관련된 모든 파일 (데이터 파일, 컨트롤 파일, 리두로그 파일, 파라메터 파일)을 같은 시점에 운영체계 명령어(UNIX의 경우는 cp, mv, ufsdump/WINDOW의 경우 copy, move 등)를 사용하여 디스크 또는 테이프 장치에 복사합니다. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] mkdir C:\BACKUP [C:\] CD C:\ORACLE\ORADATA\ORA92 [C:\] COPY *.DBF C:\BACKUP ← 데이터 파일의 백업 [C:\] COPY *.CTL C:\BACKUP ← 컨트롤 파일의 백업 [C:\] COPY *.LOG C:\BACKUP ← 라두로그 파일의 백업 [C:\] COPY C:\ORACLE\ORA92\DATABASE\*.ORA C:\BACKUP ← 파라메터 파일 백업

오라클 사에서 제공하는 오프라인 백업이라는 것은 결론적으로 운영체계 상에서 현재, 오라클 데이터베이스가 구성하고 있는 모든 파일(데이터 파일, 컨트롤 파일, 리두로그 파일, 파라메터 파일)들을 지정한 장치로 복사하는 것을 의미합니다. 이런 경우, 가장 주의해야 할 점은 백업 데이터가 저장될 디스크 또는 테이프 장치에 충분한 사용공간이 존재하는지를 확인하는 것 입니다.

또한, 한가지 더 주의해야 할 점은 반드시 관련된 모든 파일들을 복사하셔야 합니다. 
예를 들어, 오늘은 데이터 파일 만 백업하고 내일은 컨트롤 파일을 백업하고 모레에는 리두로그 파일만 백업하는 방법은 정상적인 오프라인 백업 방법이 아니며, 이렇게 백업된 데이터들은 복구 시 사용할 수 없게 됩니다. 그 이유는 다음과 같습니다.

위 그림처럼, ① 현재시점 2001년 6월 30일 SCN(시스템 변경번호)이 100 번인 경우, 데이터베이스를 종료하고 오프라인 백업을 수행하였습니다. 당시, 모든 백업 파일들은 같은 시점의 SCN 100 번인 시점의 데이터들 이었습니다.

② 한 달의 시간이 흘렀고, 현재시점 2001년 7월 31일 SCN이 101 번인 경우, 데이터베이스를 종료한 후 오프라인 백업을 수행하였습니다. 모든 백업 파일들은 SCN이 101번인 시점의 데이터들 이었습니다.

③ 또다시, 한 달의 시간이 흘렀고 현재 시점 2001년 8월 31일에 컨트롤 파일이 저장되어 있는 디스크에 장애가 발생하면서 모든 컨트롤 파일이 사용될 수 없는 치명적인 상태가 되었습니다.

이 경우, 데이터베이스를 복구하기 위해서는 마지막으로 백업되었던 2001년 7월 31일의 백업 데이터를 이용해야 합니다. 위 그림처럼, SCN이 101번을 가지고 있는 7월 31일 백업된 컨트롤 파일을 SCN이 102번을 가지고 있는 현재시점의 데이터베이스 환경으로 재설치를 하고 있습니다. 하지만, 현재 시점의 데이터베이스 환경에서 장애가 발생하지 않은 데이터 파일, 리두로그 파일들은 SCN이 102번 인데, 조금 전에 재 설치된 컨트롤 파일은 SCN이 101번을 나타내는 문제점을 가지게 됩니다.

이 경우, 데이터베이스를 시작(Startup)하게 되면 컨트롤 파일과 다른 파일들이 같은 시점의 데이터들이 아니므로 정상적으로 시작되지 않습니다.

위 그림에서, ③의 경우 데이터베이스의 OPEN 단계는 현재 컨트롤 파일, 리두로그 파일, 데이터 파일들의 SCN을 확인하여 모두 같은 시점의 SCN을 가지고 있는지를 비교하게 되는데 이때, 같은 SCN 번호가 아닌 파일이 발견되면 오라클 데이터베이스에 장애가 발생한 것으로 확인하여 더 이상 OPEN 단계를 수행하지 않으며 다음과 같은 에러 메시지를 출력하게 됩니다.(다음 예제는 USERS01.DBF 데이터 파일의 경우입니다.)

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> STARTUP MOUNT; SQL> ALTER DATABASE OPEN; alter database open * ORA-01113: 9 파일이 매체 복구되어야 합니다. ORA-01110: 9 데이터 파일: C:\ORALCE\ORADATA\ORA92\USERS01.DBF

이 에러 메시지의 의미는 USERS01.DBF 데이터 파일의 SCN 번호와 다른 데이터 파일, 컨트롤 파일, 리두로그 파일의 SCN 번호가 일치하지 않는 것을 의미합니다. 
즉, 데이터베이스에 장애가 발생한 것이며, USERS01.DBF 파일에 대한 복구가 요구 된다는 의미이기도 합니다.

결론적으로, 데이터베이스에 장애가 발생한 경우 오프라인 백업에 의해 데이터를 복구하기 위해서는 같은 시점에, 같은 SCN 번호를 가진 모든 파일들이 필요하다는 것 입니다. 
즉, 오프라인 백업 시 모든 파일을 같은 시점에 백업해야 합니다.


3) 노-아카이브 모드 또는 아카이브 모드에 관계없이 사용할 수 있습니다.

오프라인 백업 방법은 노-아카이브 모드에서 수행할 수 있으며, 앞으로 소개할 아카이브 모드에서도 수행할 수 있는 방법입니다.


다음은 오프라인 백업의 단점에 대해서 알아 보도록 하겠습니다.

1) 주요 특징에서 설명 드린 대로 이 방법은 데이터베이스를 종료(Shutdown)한 후 관련된 모든 파일들을 운영체계 상에서 복사해야 합니다. 문제는 복사해야 할 파일들의 크기가 작은 경우에는 문제되지 않겠지만, 파일들의 크기가 매우 큰 경우(몇 십, 몇 백 기가바이트 또는 테라 바이트)에는 많은 시간이 소요될 수 있기 때문에 그 동안 데이터베이스를 계속적으로 종료상태로 두어야 한다는 것 입니다. 결국, 오프라인인 백업이 수행되는 동안에 어떤 사용자도 데이터베이스에 접속할 수 없으며 데이터를 참조할 수 도 없다는 것 입니다.


2) 오프라인 백업이 수행되기 위해서는 충분한 디스크 공간이 확보되어야 합니다. 현재 데이터 파일과 리구로그 파일의 크기 만큼 사용공간이 확보되어 있어야 만 오프라인 백업을 수행할 수 있기 때문입니다. 만약, 충분한 사용공간이 확보되지 않는다면 백업작업을 효과적으로 진행할 수 없게 됩니다.


사례-1

다음 사례는 노-아카이브 모드에서 사용자의 데이터 파일이 유실되는 경우 장애를 복구하는 방법입니다. 현재, 오라클 서버는 노-아카이브 모드이며 이미 오프라인 백업방법에 의해 데이터베이스 전체 백업이 수행되어 있는 상태입니다.

어느날, 오라클 데이터베이스에 장애가 발생하였고 관련 백업 파일들을 재 설치하려고 합니다. 그런데, 모든 백업 파일들은 정상적으로 재 설치 하였는데, USERS01.DBF 파일은 원래 디스크 경로에 재 설치할 수가 없었습니다. 왜냐하면, 해당 경로의 디스크에 베드 블록(Bad Block)이 발생하여 읽기, 쓰기 작업을 더 이상 수행할 수가 없기 때문입니다.

노-아카이브 모드에서 이런 경우가 발생하면 어떻게 오라클 데이터베이스를 복구할 수 있을까요?


1) 먼저, 오프라인 백업 경로에서 백업된 파일들을 확인한 후 관련 경로에 재설치 하십시오. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\]cd c:\backup [C:\] dir System01.dbf …………………. init.ora …………………. [C:\] copy *.ctl c:\oracle\oradata\ora92\*.ctl ← 컨트롤 파일을 재설치 [C:\] copy *.dbf c:\oracle\oradata\ora92\*.dbf ← 데이터 파일을 재설치 [C:\] copy *.log c:\oracle\oradata\ora92\*.log ← 리두로그 파일을 재설치 [C:\] copy *.ora c:\oracle\ora92\database ← 파라메터 파일을 재설치 [C:\] cd c:\oracle\oradata\ora92 [C:\] dir users01.dbf redo01b.log redo02b.log log3b.log ………………. [C:\] move users01.dbf d:\oracle\oradata\users01.dbf → USERS01.DBF 파일은 원래 디스크 경로에 재설치 할 수 없어 일단 다른 디스크 경로에 재설치합니다. [C:\]cd c:\oracle\ora92 [C:\] dir users*
2) USERS01.DBF 파일은 본래 경로에 재 설치하진 못했지만 기타 모든 파일들은 재설치 하였으므로 오라클 서버를 시작해 보십시오. 오픈 단계에서 USERS01.DBF 파일의 본래 경로로부터 관련 파일을 검색해 보지만 파일이 존재하지 않으므로 에러가 발생할 것 입니다. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup mount SQL> alter database open; alter database open * ORA-01157: cannot identify data file 3 - file not found ORA-01110: data file 3: 'c:\oracle\oradata\ora92\users01.dbf' SQL> select name from v$datafile; NAME ---------------------------------------------------……………………………………. c:\oracle\oradata\ora92\users01.dbf → 오라클 서버는 USERS01.DBF 파일이 처음에 있던 디렉토리 경로에 계속 있는 걸로 알고 있습니다.
3) 이런 경우, 오라클 서버에게 재 설치된 경로가 어디인지 알려주게 되면 해당 경로로부터 관련 파일을 검색하게 됩니다. 오라클 서버의 구조 중에 관련 파일의 경로와 파일명이 저장되어 있는 곳은 컨트롤 파일입니다. 다음 명령문을 수행하게 되면 컨트롤 파일 내의 해당 정보가 변경되며 오픈 단계에서 이 정보를 통해 데이터베이스를 오픈하게 됩니다. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> alter database rename file 'c:\oracle\oradata\ora92\users01.dbf' to 'd:\oracle\ora92\users01.dbf ';
4) 다시 오라클 서버를 시작해 보십시오. 오라클 서버는 컨트롤 파일 내에 변경된 경로로부터 USERS01.DBF 파일을 검색하여 정상적으로 오픈하게 됩니다. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> alter database open; → 정상적으로 오픈 됩니다.
3-4 아카이브 모드

지금까지, 노-아카이브 모드에 대한 개념과 데이터베이스에 장애가 발생한 경우 노-아카이브 모드에서 복구하는 방법과 절차에 대해서 자세히 알아 보았습니다.

이번에는 아카이브 모드에 대해서 자세히 알아 보도록 하겠습니다.

노-아카이브 모드에서 사용자가 실행한 DML문에 의해 발생하는 모든 데이터(변경 전 데이터와 변경 후 데이터)들은 리두로그 버퍼에 백업된 다음 LGWR 프로세스에 의해 리두로그 파일에 저장됩니다. 또한, 오라클 서버는 데이터베이스 생성 시 기본적으로 3개의 리두로그 파일을 제공하며 LGWR 프로세스는 첫 번째 파일에서 두 번째 파일로, 두 번째 파일에서 세 번째 파일로 쓰기 작업을 계속하게 됩니다. 이때, 마지막 세 번째 리두로그 파일도 모두 쓰여지고 나면 다시 첫 번째 리두로그 파일로 이동하여 쓰기 작업을 계속하게 됩니다.

문제는 첫 번째 리두로그 파일에 저장되어 있던 이전 백업 데이터는 새로운 백업 데이터에 의해 재작성(Rewrite) 되어 삭제된다는 것 입니다.

"1편 오라클 서버구조와 백업/복구원리"에서도 자세히 설명 되었던 대로 리두로그 파일에 백업되는 데이터들은 장애 발생 시 데이터베이스를 복구하기 위한 용도입니다. 그런데. 이 데이터들이 LGWR 프로세스에 의해 재 작성된다는 것은 만약, 데이터베이스에 장애가 발생하는 경우 복구해야 할 백업 데이터들이 유실된다는 것을 의미합니다. 즉, 복구작업을 수행할 수 없게 된다는 것 입니다. 바로 이런 문제점을 개선하기 위해 오라클 사는 아카이브 모드(Archive Mode)라는 백업 메커니즘을 제공합니다.

위 그림에서, LGWR 프로세스가 첫 번째 리두로그 파일에 모든 변경 데이터를 저장한 후, 두 번째 리두로그 파일로 이동하는 순간, ARCH 백그라운드 프로세스는 첫 번째 리두로그 파일을 사용자가 미리 지정한 경로로 복사하게 됩니다. 
그리고, 두 번째 파일에서 세 번째 리두로그 파일로 이동할 때도 두 번째 리두로그 파일을 ARCH 프로세스가 지정한 경로로 복사합니다. 마지막으로, 세 번째 리두로그 파일에서 다시 첫 번째 리두로그 파일로 이동할 때도 세 번째 리두로그 파일을 지정한 경로로 복사하게 됩니다. 그런 후, 다시 첫 번째 파일에 백업 데이터들을 재 작성하여 저장하게 됩니다.

아카이브 모드에서는 다시 첫 번째 리두로그 파일에 백업 데이터를 저장하더라도 이전 백업데이터는 이미 사용자가 지정한 경로에 ARCH 프로세스에 의해 복사되어 있기 때문에 데이터베이스에 장애가 발생하더라도 아카이브 파일을 통해 복구작업을 수행할 수 있게 됩니다.

즉, 데이터베이스에서 발생하는 모든 데이터(변경 전 데이터와 변경 후 데이터)들이 ARCH 프로세스에 의해 항상 백업되는 메커니즘을 아카이브 모드(Archive Mode)라고 합니다.
기본적으로 오라클 데이터베이스는 노-아카이브 모드이며 설치 후 아카이브 모드로 전환하는 작업을 수행하셔야 합니다.

3-4-1 아카이브 모드의 환경설정 방법

다음은 데이터베이스를 노아카이브 모드에서 아카이브 모드로 전환하는 방법입니다.


1) 먼저, init<sid>.ora 파일에 아카이브 모드와 관련된 파라메터를 설정하십시오. </sid>

[LOG_ARCHIVE_START] 파라메터는 ARCH 백그라운드 프로세스에 의해 데이터베이스를 아카이브 모드로 전환하고 로그스위치가 발생하면 자동으로 아카이브를 실행합니다.

[LOG_ARCHIVE_DEST] 파라메터는 리두 로그 파일에 대한 아카이브 파일이 생성될 기본 저장 경로를 의미합니다.

LOG_ARCHIVE_DEST_n] 파라메터는 아카이브 경로를 여러 군데 지정할 때 사용합니다. 최대 10개의 경로지정이 가능합니다

[LOG_ARCHIVE_FORMAT] 파레메터는 [LOG_ARCHIVE_DEST] 또는 [LOG_ARCHIV E_DEST_n] 파라메터에 의해 지정된 경로에 생성될 아카이브 파일의 파일 포맷를 결정합니다.

파일의 포맷은 다음과 같습니다.

[ %s ] 자동으로 생성될 아카이브 파일의 일련번호를 결정해 줍니다. 
(예) 1, 2, 3,,, 

[ %S ] 자동으로 생성될 아카이브 파일의 일련번호를 0 값으로 채워서 결정해 줍니다. 
(예) 00001, 00002, 00003 …… 

[ %t ] 데이터베이스가 하나의 인스턴스인지 또는 여러 개의 인스턴스(OPS 환경)로 구성되어 있는지를 구분하여 표시해 줍니다. 
(예) 1, 2, 3, ,,, 

[ %T ] 데이터베이스가 하나의 인스턴스인지 또는 여러 개의 인스턴스(OPS 환경)로 구성되어 있는지를 0 값으로 채워서 결정해 줍니다. 
(예) 001, 002, 003,,,

[ %r ] 오라클 데이터베이스의 백업과 복구작업을 수행하다 보면 백업되었던 시점은 다르지만 동일한 아카이브 파일명이 생성되는 경우가 있습니다. 이런 경우, 현재 생성된 아카이브 파일과 이전에 생성된 아카이브 파일명이 동일하여 아카이브 파일을 저장, 관리하는데 혼돈을 유발시키게 됩니다. 이런 문제를 해결하기 위해 ALTER DATABASE OPEN RESETLOGS 명령어에 의해 데이터베이스가 재 시작된 후 새롭게 생성되는 아카이브 파일의 번호를 초기화할 수 있습니다. 이 구분 값은 오라클 10g 버전부터 제공됩니다.

(예) 0533062963 , 0533062973

2) 데이터베이스를 아카이브 모드로 전환하기 위해서는 데이터베이스를 다시 시작해야 하며 마운트(mount) 단계에서 'ALTER DATABASE ARCHIVELOG' 명령어를 실행해야 합니다. 
반대로, 아카이브 모드에서 노아카이브 모드로 전환할 때는 'ALTER DATABASE NOARCHIVELOG' 명령어를 실행하십시오. 아카이브 모드로 전환이 되었으면 데이터베이스를 오픈 시키십시오.
 


3) 전환작업이 완료되었으면 환경설정이 제대로 되었는지 확인해 보십시오.

다음은 사용 중인 데이터베이스에서 아카이브 모드 상태를 확인하는 방법입니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> CONNECT /AS SYSDBA SQL> ARCHIVE LOG LIST Database log mode Archive Mode ← 아카이브 모드 Automatic archival Enabled Archive destination C:\oracle\ora92\database\arch Oldest online log sequence 51 Current log sequence 53

이 결과를 참조했을 때 "Database log mode"의 결과가 "Archive Mode"임을 확인할 수 있습니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> SET LINESIZE 1000 SQL> SELECT GROUP#, SEQUENCE#, ARCHIVED, STATUS FROM V$LOG; GROUP# SEQUENCE# ARC STATUS ---------- ---------- ----- ---------------- 1 52 YES INACTIVE 2 53 NO CURRENT 3 51 NO INACTIVE

이 결과를 참조했을 때 ARC 컬럼의 값이 "YES"는 아키이브 모드라는 것을 의미합니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> SELECT ARCHIVER FROM V$INSTANCE; ARCHIVE ------- STARTED

이 결과를 참조했을 때 "STARTED"는 아키이브 모드라는 것을 의미합니다.

Posted by redkite
, |

온라인 백업방법은 반드시 아카이브 모드이어야 합니다. 왜냐하면, 오라클 서버가 사용자들에 의해 사용되고 있는 와중에 백업되는 방법이기 때문에 노-아카이브 모드에서는 수행될 수 없기 때문입니다. 만약, 어떤 데이터 파일을 온라인 백업하고 있는데 그 파일에 존재하는 테이블에 대해 누군가가 변경작업을 수행한다면 백업작업이 완료된 후 변경된 데이터를 해당 데이터 파일에 반드시 변경해야 하기 때문입니다.

 

 

6장 ON-Line 백업을 이용한 장애복구

  6-1 테이블스페이스 온라인 백업

오라클 데이터베이스를 사용하는 사용자들의 기업환경은 매우 다양합니다. 아침에 출근해서 저녁에 퇴근하는 기업이 있는가 하면, 퇴근 후에도 24시간 동안 인터넷을 통해 계속해서 고객으로부터 제품에 대한 주문 또는 서비스 요청을 받는 기업들도 있습니다. 
지금까지 소개되었던 대표적인 백업방법은 오라클 서버를 종료한 후 관련된 모든 파일들을 복사하는 방법인 오프라인(Off-Line) 백업이 소개되었습니다.
그리고, 오프라인 백업된 파일들을 통해 오라클 데이터베이스에 장애가 발생한 경우 복구하는 방법과 절차에 대해서도 자세히 알아 보았습니다.
만약, 24시간 동안 계속적인 기업활동을 수행하는 회사에서 오라클 데이터베이스를 백업하기 위해 반드시 오프라인 백업을 수행해야 한다면 백업을 수행하는 시간 동안에는 고객으로부터 어떤 주문 접수도 처리할 수 없는 상태가 될 수 밖에 없을 것 입니다.
기업 입장에서는 오라클 서버를 종료할 수도 없고, 주문접수도 수행할 수 없는 지경에 이르게 되어 궁극적으로는 불안한 시스템 운영을 할 수밖에 없을 것 입니다. 
이런 문제점을 해결하기 위해, 오라클 사는 24시간 365일 동안 데이터베이스를 사용하는 기업환경에서 오라클 서버를 종료하지 않고도 효과적인 백업작업을 수행할 수 있도록 온라인(On-Line) 백업방법을 제공하고 있습니다.
이 백업방법은 오픈(OPEN) 백업 또는 핫(HOT) 백업방법이라고 불리어지기도 합니다.
그리고, 온라인 백업은 반드시 아카이브 모드에서 만 수행할 수 있는 백업방법 입니다.
온라인 백업에는 2가지 백업 방법이 있습니다. 첫 번째는 테이블스페이스 단위의 백업이며 두 번째는 전체 데이터베이스 온라인 백업 방법입니다. 첫 번째 방법은 오라클 10g 이전 버전에서도 제공되었으며 두 번째 방법은 10g 버전부터 제공되었습니다. 
자~ 그럼, 테이블스페이스 단위의 온라인 백업 방법부터 자세히 알아 보도록 합시다.

다음은 온라인 백업의 방법과 절차에 대한 자세한 설명입니다.

(1) 먼저, 오라클 데이터베이스는 사용 가능한 상태이어야 합니다. STARTUP 명령어에 의해 정상적으로 시작되어야 하며 사용자들의 SELECT, UPDATE, INSERT, DELETE 작업이 정상적으로 수행 가능해야 합니다.

(2) 다음은, 오라클 데이터베이스가 아카이브 모드로 운영되고 있는지 확인하십시오. 
온라인 백업방법은 반드시 아카이브 모드이어야 합니다. 왜냐하면, 오라클 서버가 사용자들에 의해 사용되고 있는 와중에 백업되는 방법이기 때문에 노-아카이브 모드에서는 수행될 수 없기 때문입니다. 만약, 어떤 데이터 파일을 온라인 백업하고 있는데 그 파일에 존재하는 테이블에 대해 누군가가 변경작업을 수행한다면 백업작업이 완료된 후 변경된 데이터를 해당 데이터 파일에 반드시 변경해야 하기 때문입니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> archive log list 데이터베이스 로그모드 아카이브 모드 가장 오래된 온라인 로그순서 1 아카이브할 다음 로그 1 현재 로그순서 1

(3) 다음은, 해당 테이블스페이스에 대한 온라인 백업하는 방법입니다. 온라인 백업은 테이블스페이스 단위로 관련된 데이터 파일을 복사할 수 있습니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> MKDIR C:\ONLINE_BACKUP -- SYSTEM 테이블스페이스에 대한 온라인 백업 SQL> ALTER TABLESPACE SYSTEM BEGIN BACKUP; SQL> HOST COPY c:\oracle\oradata\ora92\system01.dbf c:\online_backup SQL> ALTER TABLESPACE SYSTEM END BACKUP; --TEMP 테이블스페이스에 대한 온라인 백업 SQL> ALTER TABLESPACE TEMP BEGIN BACKUP; SQL> HOST COPY c:\oracle\oradata\ora92\temp01.dbf c:\online_backup SQL> ALTER TABLESPACE TEMP END BACKUP; -- UNDOTBS 테이블스페이스에 대한 온라인 백업 SQL> ALTER TABLESPACE UNDOTBS BEGIN BACKUP; SQL> HOST COPY c:\oracle\oradata\ora92\undotbs01.dbf c:\online_backup SQL> ALTER TABLESPACE UNDOTBS END BACKUP; -- QUERY 테이블스페이스에 대한 온라인 백업 SQL> ALTER TABLESPACE QUERY BEGIN BACKUP; SQL> HOST COPY c:\oracle\oradata\ora92\query01.dbf c:\online_backup SQL> ALTER TABLESPACE QUERY END BACKUP;
< 주의 >
온라인 백업을 수행하면서 가장 주의해야 할 점은 ALTER TABLESPACE ~ BEGIN BACKUP; 명령문과 ALTER TABLESPACE ~ END BACKUP; 명령문을 수행하는 시간의 차이입니다. 
BEGIN BACKUP문을 실행하는 순간부터 관련 테이블스페이스의 모든 파일들에는 CHECKPOINT가 더 이상 발생하지 않게 되며 END BACKUP문을 실행하는 순간 CHECKPOINT가 다시 발생하게 됩니다.(CHECKPOINT의 기본원리에 대해서는 "2편 데이터베이스의 논리적/물리적 구조설계"를 참조 하십시오.) 
오라클 서버는 이러한 원리에 의해, 해당 테이블스페이스에 대한 백업시점을 관리하게 됩니다. 결론적으로 테이블스페이스를 생성할 때 너무 큰 크기의 데이터 파일을 생성하게 되면 온라인 백업을 수행할 때 CHECKPOINT의 시점관리에 문제가 발생하여 에러가 발생할 수도 있습니다. 너무 큰 크기의 데이터 파일들은 2~3개 정도로 나누어 스트라이핑(Striping) 하시는 것이 원활한 백업과 복구작업에 도움이 될 수 있습니다.

(4) 온라인 백업된 모든 데이터 파일들을 확인하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] CD C:\ONLINE_BACKUP [C:\] DIR SYSTEM01.DBF UNDOTBS01.DBF TEMP01.DBF QUERY01.DBF
6-2 데이터베이스 전체 온라인 백업

오라클 사에서 제공하는 2가지 온라인 백업방법 중에 먼저 테이블스페이스 단위의 백업 방법을 알아 보았습니다. 
온라인 백업방법은 24시간 365일 동안 오라클 데이터베이스를 종료할 수 없는 기업환경에서 매우 적절하게 수행할 수 있는 백업방법 중에 하나라는 것은 두말하면 잔소리일 것 입니다. 하지만, 이 백업방법의 가장 큰 단점은 오라클 데이터베이스를 구성하고 있는 모든 테이블스페이스에 대한 전체 백업이 요구되는 경우입니다.
ALTER TABLESPACE ~ BEGIN BACKUP과 ALTER TABLESPACE ~ END BACKUP 명령어를 반복적으로 수행해야 하기 때문에 번거로울 뿐만 아니라 READ ONLY 모드의 테이블스페이스와 OFFLINE 모드의 테이블스페이스에 대해서는 수행할 수 없는 것이 단점이기도 합니다.
이러한 문제점을 개선한 백업방법이 바로 전체 데이터베이스 온라인 백업방법 입니다.
이 백업방법은 오라클 10g 버전부터 제공됩니다.


(1) ALTER DATABASE BEGIN BACKUP과 ALTER DATABASE END BACKUP 명령어

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> ALTER DATABASE BEGIN BACKUP; ← 전체 DB 온라인 백업 시작 SQL> host copy c:\oracle\oradata\ora92\system01.dbf c:\full_online_backup SQL> host copy c:\oracle\oradata\ora92\undotbs01.dbf c:\full_online_backup SQL> host copy c:\oracle\oradata\ora92\temp01.dbf c:\full_online_backup SQL> host copy c:\oracle\oradata\ora92\temp02.dbf c:\full_online_backup SQL> host copy c:\oracle\oradata\ora92\users01.dbf c:\full_online_backup SQL> host copy c:\oracle\oradata\ora92\query01.dbf c:\full_online_backup SQL> ALTER DATABASE END BACKUP; ← 전체 DB 온라인 백업의 종료

(2) 오프라인 상태의 테이블스페이스는 테이블스페이스 단위의 온라인 백업을 수행할 수 없지만, 전체 데이터베이스 온라인 백업방법으로는 가능합니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> ALTER TABLESPACE users OFFLINE IMMEDIATE; SQL> SELECT tablespace_name, status FROM dba_tablespaces; TABLESPACE_NAME STATUS ------------------------------ --------- SYSTEM ONLINE UNDOTBS ONLINE TEMP ONLINE USERS OFFLINE SQL> ALTER TABLESPACE users BEGIN BACKUP; * ERROR at line 1: ORA-01128 : cannot start online backup - file 4 is offline ORA-01110 : data file 4 : 'c:\oracle\oradata\ora92\users01.dbf' SQL> ALTER DATABASE BEGIN BACKUP; SQL> host copy c:\oracle\oradata\ora92\users01.dbf c:\full_online_backup SQL> ALTER DATABASE END BACKUP;

(3) READ ONLY 상태의 테이블스페이스는 테이블스페이스 단위의 온라인 백업을 수행할 수 없지만, 전체 데이터베이스 온라인 백업방법으로는 가능합니다

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> select tablespace_name, status from dba_tablespaces; TABLESPACE_NAME STATUS ------------------------------------ QUERY READ ONLY ← READ ONLY 상태를 확인하십시오. SQL> ALTER TABLESPACE query BEGIN BACKUP; alter tablespace users begin backup 1행에 오류: ORA-01642: 읽기 전용 'USERS' 테이블스페이스에는 초기 백업이 필요하지 않습니다. SQL> ALTER DATABASE BEGIN BACKUP; SQL> host copy c:\oracle\oradata\ora92\query01.dbf c:\full_online_backup SQL> ALTER DATABASE END BACKUP;
6-3 온라인 백업을 이용한 완전 복구

온라인 백업파일을 이용한 오라클 데이터베이스의 복구방법에 대해서 알아 보도록 하겠습니다. 지금까지 대부분의 사례 내용들이 오프라인 백업파일을 이용한 복구 방법이었다면 이번 사례는 온라인 백업된 파일을 이용하는 방법입니다.
결론적으로 말씀 드리면, 오라클 데이터베이스의 모든 복구방법은 백업된 파일이 오프라인 백업 파일이든, 온라인 백업 파일이든 상관없이 모두 동일한 방법과 절차에 의해 수행하게 됩니다. 지금부터 설명하는 방법과 절차는 이미 소개된 완전복구 방법과 동일합니다. 다만, 복구작업을 수행할 때 온라인 백업된 파일을 이용하는 것 입니다.

위 그림에서, 현재 시점 2001년 6월 10일 오전 12시에 데이터베이스의 상태에서 온라인 백업을 통해 SCN 번호가 95인 USERS01.DBF 데이터 파일을 백업하고 있습니다. 현재, 데이터베이스는 아카이브 모드이며, 온라인 백업 이후 발생한 모든 트랜잭션 데이터들은 아카이브 파일과 리두로그 파일에 기록되어 있습니다. 첫 번째 아카이브 파일 ARC1.LOG 에는 마지막 오프라인 백업 이후부터 2001년 6월 11일 오전 12시까지의 백업 데이터들이 저장 되었다고 합니다. 그리고, 두 번째 아카이브 파일 ARC2.LOG 에는 2001년 6월 11일 오전 12시부터 2001년 6월 12일 오전 12시까지의 백업 데이터들이 저장되었으며, 2001년 6월 12일 오전 12시부터 6월 12일 오후 13시까지의 데이터들은 ARC3.LOG 파일에 기록되어 있다고 합니다.
현재시점, 2001년 6월 12일 오후 13시에 USERS01.DBF 데이터 파일이 저장되어 있는 디스크에 장애가 발생하여 더 이상 데이터베이스를 사용할 수 없다고 합니다.


사례-9

컨트롤 파일들이 저장되어 있는 모든 디스크에 장애가 발생하였습니다. 또한 모든 데이터 파일이 저장되어 있던 디스크에도 치명적인 문제가 발생하였습니다. 마지막, 온라인 백업 파일을 이용하여 완전 복구작업을 수행해 보도록 하겠습니다.


(1) 오라클 서버가 사용 가능한 상태인지 확인하고 MOREDEPT.SQL을 실행한 후 아카이브 파일들이 정상적으로 생성되는지 확인하십시오

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup SQL> @moredept alter system switch logfile; insert into scott.dept values(1,'Personnel','Pusan'); insert into scott.dept values(2,'Account','Pusan'); insert into scott.dept values(3,'Q.C','Pusan'); alter system switch logfile; insert into scott.dept values(4,'Personnel','Seoul'); insert into scott.dept values(5,'Account','Seoul'); insert into scott.dept values(6,'Q.C','Seoul'); alter system switch logfile; insert into scott.dept values(7,'Personnel','Daejeon'); insert into scott.dept values(8,'Account','Daejeon'); insert into scott.dept values(9,'Q.C','Daejeon'); commit; select count(*) from scott.dept; SQL> host dir c:\oracle\ora92\database\arch\*.arc

(2) 이번 시나리오는 모든 컨트롤 파일과 데이터 파일이 함께 장애가 발생했다고 합니다.
마지막으로 온라인 백업된 파일을 이용하여 오라클 데이터베이스를 복구해 봅시다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> shutdown abort ← 갑작스런 정전상태를 만들기 위해 ABORT 옵션으로 오라클 서버를 강제 종료합니다. SQL> exit [C:\] del c:\oracle\oradata\ora92\system01.dbf [C:\] del c:\oracle\oradata\ora92\undotbs01.dbf [C:\] del c:\oracle\oradata\ora92\temp01.dbf [C:\] del c:\oracle\oradata\ora92\temp02.dbf [C:\] del c:\oracle\oradata\ora92\users01.dbf [C:\] del c:\oracle\oradata\ora92\query01.dbf → 모든 데이터 파일들에 장애가 발생합니다. [C:\] del c:\oracle\oradata\ora92\*.ctl → 모든 컨트롤 파일들에 장애가 발생합니다.

(3) 자~ 지금부터 온라인 백업파일을 이용하여 완전복구 작업을 수행해 보도록 하겠습니다.
먼저, 장애가 발생한 모든 컨트롤 파일과 데이터 파일에 대한 온라인 백업 파일들을 현재 경로로 재 설치하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] cd c:\online_backup [C:\] dir [C:\] copy system01.dbf c:\oracle\oradata\ora92 [C:\] copy undotbs01.dbf c:\oracle\oradata\ora92 [C:\] copy temp01.dbf c:\oracle\oradata\ora92 [C:\] copy temp02.dbf c:\oracle\oradata\ora92 [C:\] copy users01.dbf c:\oracle\oradata\ora92 [C:\] copy query01.dbf c:\oracle\oradata\ora92 → 장애가 발생한 모든 데이터 파일들을 재 설치합니다. [C:\] copy backup_control.ctl c:\oracle\oradata\ora92\control01.ctl [C:\] copy backup_control.ctl c:\oracle\oradata\ora92\control02.ctl [C:\] copy backup_control.ctl c:\oracle\oradata\ora92\control03.ctl [C:\] copy backup_control.ctl c:\oracle\oradata\ora92\control04.ctl → 장애가 발생한 모든 컨트롤 파일들을 재 설치합니다. 만약, 컨트롤 파일의 개수가 4개이면 백업된 파일을 4번 해당 경로에 복사해야 합니다. [C:\] cd [C:\] sqlplus "/as sysdba" SQL> startup mount SQL> recover database using backup controlfile → 복구해야 할 대상 파일에 이전의 컨트롤 파일이 포함되어 있으므로 USING BACKUP CONTROLFILE 옵션절을 사용하여 복구작업을 수행해야 합니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed ORA-00280: Change 8050 for thread 1 is in sequence #5 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} AUTO ← AUTO 키워드를 사용하여 모든 아카이브 파일을 적용합니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed ORA-00280: Change 8050 for thread 1 is in sequence arch_n.arc ERROR 발생 ← AUTO 키워드를 적용하여 아카이브를 적용했지만 마지막 아카이브 파일 을 적용할 때 에러가 발생하는 경우가 있습니다. 왜냐하면, 적용해야 할 마지막 백업 데이터는 아카이브 파일에 저장되어 있지 않고 CURRENT 리두로그 파일에 존재하기 때문입니다. SQL> recover database using BACKUP controlfile; → 에러가 발생하는 경우에는 다시 RECOVER DATABASE ~ 명령어를 실행하십시오. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed ORA-00280: Change 8050 for thread 1 is in sequence arch_n.arc Specify log: {<ret>=suggested | filename | AUTO | CANCEL} c:\oracle\oradata\ora92\redo01.log ← 마지막 백업 데이터가 저장되어 있는 CURRENT 리두로그 파일을 입력해 주십시오. Log Applied. Media Complete Recovery. ← 복구작업이 완료되었습니다. SQL> alter database open resetlogs; → 백업된 컨트롤 파일을 이용한 복구작업은 수행과정과 절차는 완전복구 방법과 동일하지만, OPEN 단계에서 반드시 RESETLOGS 옵션을 사용해야 합니다. 왜냐하면, 컨트롤 파일은 현재 시점으로 복구되었지만 데이터베이스 내의 상태정보는 여전히 일치하지 않기 때문입니다. 반드시, 모든 상태정보를 초기화 해야만 OPEN 할 수 있습니다. SQL> select count(*) from scott.dept; → 정상적으로 복구된 것을 확인하십시오. SQL> shutdown SQL> exit</ret></ret>

(4) 불완전 복구를 수행하고 나면 반드시 이전의 마지막 백업파일은 재 사용될 수 없기 때문에 다시 오프라인 백업을 수행해야 합니다. 또한, 이전의 아카이브 파일, 트레이스 파일들도 제거 하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] copy c:\oracle\oradata\ora92\*.* c:\backup [C:\] copy c:\oracle\admin\ora92\init.ora c:\backup [C:\] del c:\oracle\oradata\ora92\arch\*.arc
사례-9

데이터베이스의 컨트롤 파일이 존재하는 디스크에 장애가 발생하여 더 이상 입력, 수정, 삭제 작업을 수행할 수 없습니다. 모든 컨트롤이 유실된 상태이며 마지막으로 백업된 컨트롤 파일 만이 사용 가능한 상태입니다. 어떻게 복구해야 할까요 ?


(1) 오라클 서버가 사용 가능한 상태인지 확인하고 MOREDEPT.SQL을 실행한 후 아카이브 파일들이 정상적으로 생성되는지 확인하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup SQL> @moredept alter system switch logfile; insert into scott.dept values(1,'Personnel','Pusan'); insert into scott.dept values(2,'Account','Pusan'); insert into scott.dept values(3,'Q.C','Pusan'); alter system switch logfile; insert into scott.dept values(4,'Personnel','Seoul'); insert into scott.dept values(5,'Account','Seoul'); insert into scott.dept values(6,'Q.C','Seoul'); alter system switch logfile; insert into scott.dept values(7,'Personnel','Daejeon'); insert into scott.dept values(8,'Account','Daejeon'); insert into scott.dept values(9,'Q.C','Daejeon'); commit; select count(*) from scott.dept; SQL> host dir c:\oracle\ora92\database\arch\*.arc

(2) 이번 사례는 데이터베이스의 모든 상태정보와 오라클 서버의 시작과 종료 시 반드시 필요한 컨트롤 파일에 대한 내용입니다. 
여러 개의 컨트롤 파일 중 하나라도 장애가 발생하면 더 이상 오라클 서버를 사용할 수 없기 때문에 오라클 데이터베이스 구조 중에 가장 중요한 파일 중에 하나입니다. 
먼저, 현재 사용하고 있는 오라클 서버에서 컨트롤 파일의 위치와 개수를 확인하십시오. 그리고, 모든 컨트롤 파일을 삭제하여 장애가 발생한 시나리오를 만들어 보시기 바랍니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> shutdown abort --> 오라클 서버가 비정상적으로 종료됩니다. SQL> exit [C:\] del c:\oracle\oradata\ora92\*.ctl ← 사용자의 실수로 인해 모든 컨트롤 파일이 삭제됩니다. (실제 기업환경에서는 임의로 컨트롤 파일을 삭제해서는 안됩니다.)

(3) 결론적으로 모든 컨트롤 파일에 장애가 발생하면 더 이상 오라클 데이터베이스를 사용할 수 없게 됩니다. 이런 현상이 발생하는 경우에는 불완전 복구방법을 사용합니다. 
마지막 오프라인 백업된 백업 파일로부터 모든 컨트롤 파일을 현재 경로로 재 설치하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\]copy c:\backup\*.ctl c:\oracle\oradata\ora92\*.ctl [C:\] sqlplus "/as sysdba" SQL> startup mount SQL> recover database using BACKUP controlfile ← 현재 환경은 컨트롤 파일 만 이전의 백업 파일이고 다른 파일들은 현재 시점의 파일들이기 때문에 컨트롤 파일 만의 복구작업을 수행하기 위해 USING BACKUP CONTROLFILE 절을 사용하여 복구작업을 수행해야 합니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed for thread 1 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} C:\oracle\oradata\ora92\arch\arch_1.arc ← 만약, 적용해야 할 아카이브 파일이 지정되지 않으면 직접 첫 번째 아카 이브 파일의 경로와 이름을 입력해야 합니다. 적용해야 할 아카이브 파일 명이 출력되는 경우에는 AUTO 키워드를 입력하여 자동으로 아카이브를 적용하시면 됩니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed ORA-00280: Change 8050 for thread 1 is in sequence arch_2.arc Specify log: {<ret>=suggested | filename | AUTO | CANCEL} AUTO ← 첫 번째 아카이브를 적용하면 두 번째 아카이브 파일의 이름과 경로가 출력되고 해당 파일을 적용할 것 인지가 나타납니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed ORA-00280: Change 8050 for thread 1 is in sequence arch_n.arc ← 여러 개의 아카이브 파일을 적용하다 마지막 아카이브 파일을 적용하려고 했을 때 에러가 발생할 수 도 있습니다. 이런 경우는 적용해야 할 마지막 백업 데이터가 아카이브 파일로 저장되어 있는 것이 아니라, CURRENT 리두 로그 파일에 저장되어 있기 때문입니다. 이러 경우에는 마지막 CURRENT 리두로그 파일의 경로와 이름을 지정해 주시면 됩니다. SQL> recover database using BACKUP controlfile 에러가 발생하면 다시 리두로그 파일을 적용해 줄 수 없으므로 RECOVER DATABASE 명령어를 재 수행하시면 됩니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed ORA-00280: Change 8050 for thread 1 is in sequence arch_n.arc Specify log: {<ret>=suggested | filename | AUTO | CANCEL} c:\oracle\oradata\ora92\redo01.log --> 마지막 CURRENT 리두로그 파일명을 입력하십시오 Log applied. Media recovery complete. SQL> alter database open resetlogs; ← 절차와 방법은 완전복구 방법과 같지만 결론적으로 이 방법은 불완전 복구입니다. 왜냐하면, 데이터베이스의 모든 상태정보가 저장되어 있는 컨트롤 파일이 삭제되었 기 때문에 컨트롤 파일은 복구되었지만 상태정보는 복구되지 않았기 때문입니다. SQL> select count(*) from scott.dept; --> 정상적으로 검색이 가능합니다. SQL> shutdown SQL> exit</ret></ret></ret>

(4) 불완전 복구를 수행하고 나면 반드시 이전의 마지막 백업파일은 재 사용될 수 없기 때문에 다시 오프라인 백업을 수행해야 합니다. 또한, 이전의 아카이브 파일, 트레이스 파일들도 제거 하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] cd c:\oracle\oradata\ora92 [C:\] copy *.* c:\backup [C:\] copy c:\oracle\ora92\database\init.ora c:\backup
사례-10

현재, 데이터베이스는 아카이브 모드입니다. 최근에 온라인 백업과 오프라인 백업도 정상적으로 수행되었습니다. 
백업 작업 이후에 새로운 데이터 파일이 생성되었고 사용자의 데이터가 입력되었습니다.
하지만, 곧 해당 디스크에 장애가 발생하였습니다. 마지막 백업파일에는 존재하지 않는 새로 생성된 데이터 파일은 어떻게 복구할 수 있을까요 ?


(1) 오라클 서버가 사용 가능한 상태인지 확인하고 MOREDEPT.SQL을 실행한 후 아카이브 파일들이 정상적으로 생성되는지 확인하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup SQL> @moredept alter system switch logfile; insert into scott.dept values(1,'Personnel','Pusan'); insert into scott.dept values(2,'Account','Pusan'); insert into scott.dept values(3,'Q.C','Pusan'); alter system switch logfile; insert into scott.dept values(4,'Personnel','Seoul'); insert into scott.dept values(5,'Account','Seoul'); insert into scott.dept values(6,'Q.C','Seoul'); alter system switch logfile; insert into scott.dept values(7,'Personnel','Daejeon'); insert into scott.dept values(8,'Account','Daejeon'); insert into scott.dept values(9,'Q.C','Daejeon'); commit; select count(*) from scott.dept; SQL> host dir c:\oracle\ora92\database\arch\*.arc

(2) 마지막 백업 이후에 NEW_DATA 테이블스페이스가 추가로 생성되었다고 합니다. 그리고, NEW_TEST 테이블을 NEW_DATA 테이블스페이스에 생성한다고 합니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> create tablespace new_data datafile 'c:\oracle\oradata\ora92\new_data.dbf' size 500k; SQL> create table scott.new_test tablespace new_data as select * from scott.dept; SQL> @moredept.sql

(3) 갑작스런 정전이 발생하고 새로 생성한 NEW_DATA 테이블스페이스에 장애가 발생한다고 합니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> shutdown abort ← 갑작스런 정전이 발생합니다. SQL> exit [C:\] dir c:\oracle\oradata\ora92 [C:\] del c:\oracle\oradata\ora92\new_data.dbf a NEW_DATA 테이블스페이스에 장애가 발생합니다. [C:\] dir c:\oracle\oradata\ora92

(3) 그런데, 문제가 있군요 ~ 
NEW_DATA 테이블스페이스는 마지막 백업 시에는 존재하지 않던 데이터 파일이기 때문에 복구작업을 수행하기 위해 재 설치할 백업 파일이 존재하지 않기 때문입니다. 
백업 파일이 존재하지 않는 복구는 어떻게 수행해야 할까요 ? 
결론적으로 말하면, 마지막 백업 이후에 발생한 모든 작업내용은 리두로그 파일과 아카이브 파일에 남아있기 때문에 오라클 서버가 아카이브 모드라면 쉽게 복구할 수 있습니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup ORA-01157: 데이터 4 파일을 식별 또는 잠금할 수 없습니다-DBWR 추적파일 ORA-01110: data file 7: ' dir c:\oracle\oradata\ora92\new_data.dbf' SQL> alter database create datafile 'c:\oracle\oradata\ora92\new_data.dbf' as 'c:\oracle\oradata\ora92\new_data.dbf'; → 아카이브 파일에는 모든 작업에서 발생한 변경 데이터 만 존재하기 때문에 데이터 파일(NEW_DATA.DBF)에 대한 구조는 별도로 생성해 주어야 합니다. SQL> host dir c:\oracle\oradata\ora92 SQL> recover datafile 'c:\oracle\oradata\ora92\new_data.dbf' AUTO ← 새로 생성해준 NEW_DATA.DBF 파일에 아카이브 파일이 가지고 있는 백업 데이터를 적용하여 복구작업을 수행합니다. Log Applied. Media Complete Recovery. SQL> alter database open;

(4) 백업 파일이 없는 데이터 파일은 새로운 데이터 파일을 생성한 후 아카이브 파일을 적용하면 복구작업을 수행할 수 있습니다. 데이터들이 정상적으로 복구되었는지 확인하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> select count(*) from scott.new_test;

Posted by redkite
, |

완전복구(Complete Recovery) 방법은 데이터베이스에 장애가 발생한 경우 그 시점까지의 모든 백업 데이터를 아카이브 파일과 리두로그 파일에 저장해 둔 후 복구 작업 시 사용하는 방법입니다. 실제 기업환경에서 데이터베이스를 운영하다 보면 예기치 못한 원인으로 인해 장애가 발생하는 경우 거의 대부분의 경우는 문제가 발생한 시점까지 모든 데이터를 복구하는 것이 원칙일 것 입니다. 하지만, 특별한 경우에는 문제가 생긴 시점이 아닌 그 이전 시점의 어느 순간까지 만 복구해야 하는 경우도 때로는 발생하게 됩니다. 이런 경우, 완전복구 방법으로는 과거 어느 시점까지의 복구는 할 수 없기 때문에, 반드시 불완전 복구방법을 사용해야 합니다.

 

5장 OFF-Line 백업을 이용한 불완전 복구

  5-1 불완전 복구

완전복구(Complete Recovery) 방법은 데이터베이스에 장애가 발생한 경우 그 시점까지의 모든 백업 데이터를 아카이브 파일과 리두로그 파일에 저장해 둔 후 복구 작업 시 사용하는 방법입니다. 실제 기업환경에서 데이터베이스를 운영하다 보면 예기치 못한 원인으로 인해 장애가 발생하는 경우 거의 대부분의 경우는 문제가 발생한 시점까지 모든 데이터를 복구하는 것이 원칙일 것 입니다. 
하지만, 특별한 경우에는 문제가 생긴 시점이 아닌 그 이전 시점의 어느 순간까지 만 복구해야 하는 경우도 때로는 발생하게 됩니다. 이런 경우, 완전복구 방법으로는 과거 어느 시점까지의 복구는 할 수 없기 때문에, 반드시 불완전 복구방법을 사용해야 합니다.

오라클 사에서는 시간기반 불완전 복구(Time Based Incomplete Recovery), 취소기반 불완전 복구(Cancel Based Incomplete Recovery), 변경기반 불완전 복구(Change Based Incomplete Recovery) 방법을 제공하고 있습니다.


5-1-1 시간기반 불완전 복구

자~ 그럼, 불완전 복구의 대표적 방법인 시간기반 복구에 대해서 먼저 알아보겠습니다. 데이터베이스를 운영하다 보면 대부분의 경우는 물리적 구조(시스템, 디스크 장치 등)의 장애로 인해 더 이상 데이터베이스를 사용할 수 없는 경우를 보게 됩니다. 하지만, 사용자가 DML문을 수행한 후 실수로 COMMIT문을 실행하게 되는 경우나 DROP 또는 ALTER 문장으로 원치 않게 데이터가 변경되는 경우가 발생하게 됩니다.

시간기반 불완전 복구방법은 주로 사용자의 실수로 인해 해당 테이블의 데이터가 변경되어 데이터베이스의 신뢰성이 깨지는 경우 데이터베이스를 변경 이전상태로 복구하기 위해 사용되는 복구방법 중에 하나 입니다.

위 그림에서, 현재 시점 2001년 6월 10일 오전 12시에 데이터베이스를 종료한 후 오프라인 백업을 통해 SCN 번호가 95인 모든 파일(데이터 파일, 컨트롤 파일, 리두로그 파일)들을 백업하고 있습니다. 현재, 데이터베이스는 아카이브 모드이며, 오프라인 백업 이후 발생한 모든 트랜잭션 데이터들은 아카이브 파일과 리두로그 파일에 기록되어 있습니다. 
ARC1.LOG, ARC2.LOG, ARC3.LOG 파일에 모든 백업 데이터들이 저장되었다고 합니다. 
현재시점, 2001년 6월 11일 오후 12시 10분 11초에 사용자가 실수로 EMP 테이블을 삭제했다고 합니다. 이 사실을 모른체 사용자들은 다른 테이블에 대해 입력, 수정, 삭제작업을 계속 수행했다고 합니다. 현재시점, 2001년 6월 12일 13시 USERS01.DBF 데이터 파일이 저장되어 있는 디스크에 장애가 발생하여 더 이상 데이터베이스를 사용할 수 없다고 합니다. 
데이터베이스 관리자는 완전복구 방법을 통해 장애가 발생한 USERS01.DBF 데이터 파일을 복구하려고 합니다. 하지만, 완전복구 작업을 수행하게 되면 EMP 테이블은 여전히 DROP된 상태로 복구되기 때문에 테이블을 복구할 수 없다고 합니다. EMP 테이블이 복구되기 위해서는 장애가 발생한 시점까지 복구해서는 안되며, EMP 테이블이 DROP 되기 이전 상태까지만 복구해야 합니다.

사례-7.

사용자가 실수로 테이블을 DROP 했다고 합니다. 완전복구 작업을 수행하게 되면 해당 테이블이 삭제된 상태로 복구되기 때문에 반드시 불완전 복구작업을 수행해야 합니다.


(1) 오라클 서버가 사용 가능한 상태인지 확인하고 MOREDEPT.SQL을 실행한 후 아카이브 파일들이 정상적으로 생성되는지 확인하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> @moredept.sql alter system switch logfile; insert into scott.dept values(1,'Personnel','Pusan'); insert into scott.dept values(2,'Account','Pusan'); insert into scott.dept values(3,'Q.C','Pusan'); alter system switch logfile; insert into scott.dept values(4,'Personnel','Seoul'); insert into scott.dept values(5,'Account','Seoul'); insert into scott.dept values(6,'Q.C','Seoul'); alter system switch logfile; insert into scott.dept values(7,'Personnel','Daejeon'); insert into scott.dept values(8,'Account','Daejeon'); insert into scott.dept values(9,'Q.C','Daejeon'); commit; select count(*) from scott.dept;

(2) 데이터베이스를 사용하던 중 개발자가 실수로 DEPT 테이블을 삭제하였다고 합니다. 이 테이블은 전체 업무에서 사용되는 아주 중요한 데이터를 저장하고 있기 때문에 반드시 필요한 테이블이라고 합니다. 하지만, DROP 명령어는 AUTO-COMMIT을 자동 수행하기 때문에 삭제된 테이블은 더 이상 사용할 수 없게 됩니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> host date → 현재 날짜를 메모해 두십시오. SQL> host time → 현재 시간을 메모해 두십시오, SQL> drop table scott.dept cascade constraints; --> 개발자가 실수로 DEPT 테이블을 삭제하였다고 합니다. SQL> select * from scott.dept; select * from scott.dept * ERROR at line 1: ORA-00942: table or view does not exist

(3) 지금까지 대부분의 시나리오는 운영체계 상에서 관련된 파일들을 더 이상 사용할 수 없게 되는 경우에 대한 물리적 복구 방법이었다면, 이번 시나리오는 데이터베이스 내에서 중요한 테이블이 삭제된 경우의 논리적 복구방법을 소개하게 될 것 입니다. 이전에 오프라인 백업된 파일들 중에 모든 데이터 파일들 만 해당 경로에 재설치 하십시오. 
반드시, 데이터 파일들 만 재 설치하셔야 하며 컨트롤 파일과 리두로그 파일들은 정상적으로 사용 가능한 상태이므로 재 설치하실 필요는 없습니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> shutdown immediate SQL> exit [C:\] cd c:\backup [C:\] copy *.dbf c:\oracle\oradata\ora92 → 반드시, 모든 데이터 파일들 만 재 설치하십시오.

(4) 자, 그럼, 삭제된 하나의 테이블을 복구하기 위해 시간기반 불완전 복구작업을 수행해 보도록 하겠습니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup mount SQL> recover database until time '2001-01-23:16:44:47'; ORA-00279: Change 7220 generated at 02/24/97 23:51:30 needed ORA-00289: Suggestion : c:\oracle\oradata\ora92\arch\arch_219.arc ORA-00280: Change 7220 for thread 1 is in sequence #219 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} Auto ← 관련된 모든 아카이브 파일들을 자동으로 적용해 줍니다. Media Complete Recovery → 마지막, 오프라인 백업파일을 재 설치하고 그 이후에 생성된 아카이브 파일들을 순차적으로 적용하면서 실수로 테이블을 DROP한 이전 시점까지 만 복구한다면 삭제된 테이블을 복구할 수 있을 것 입니다. (2) 단계에서 메모해 둔 날자와 시간정보를 'YYYY-MM-DD HH:MM:SI'포맷으로 정의하시면 됩니다. 반드시, 날자 포맷을 임의로 변경해서는 안됩니다. SQL> alter database open resetlogs; → 불완전 복구가 수행되었으면 데이터베이스를 RESETLOG 옵션을 사용하여 OPEN 하십시오. 불완전 복구에 의한 복구작업 시에는 반드시 이 옵션을 사용하셔야 합니다. 현재, 데이터베이스는 과거 DEPT 테이블이 삭제되기 이전 상태로 복구된 상태 입니다. 그런데, 컨트롤 파일과 리두로그 파일은 복구작업을 수행하기 이전의 현 상태 에 대한 정보를 가지고 있기 때문에 시점이 일치하지 않는 문제점이 발생하게 됩니다. 결국, 이 상태에서는 데이터베이스를 정상적으로 OPEN 할 수 없기 때문에 RESETLOG 옵션을 사용하여 모든 상태정보를 초기화할 수 밖에 없게 됩니다. SQL> archive log list 데이터베이스 로그모드 아카이브 모드 가장 오래된 온라인 로그순서 1 ← 상태정보가 초기화된 것을 확인하십시오. 아카이브할 다음 로그 1 현재 로그순서 1 SQL> select * from scott.dept; → 삭제되었던 DEPT 테이블이 다시 검색됩니다. 현재, 데이터베이스는 DEPT 테이블이 삭제되기 이전 상태로 복구되어 있기 때문에 DEPT 테이블을 검색할 수 있는 것 입니다. SQL> shutdown immediate SQL> exit</ret>

5) 불완전 복구가 완료되었으면 현재 시점의 오프라인 백업을 수행하십시오. 대부분의 개발자들이 불완전 복구를 수행한 후 오프라인 백업을 수행하지 않다가 여가지 문제로 인해 데이터베이스를 복구하지 못하는 경우가 종종 발생합니다. 현재 시점에서는 마지막 오프라인 백업된 파일들은 더 이상 복구작업에 사용될 수 없는 무의미한 파일들에 불과합니다. 이유는 불완전 복구를 수행하게 되면, 데이터베이스 내의 모든 상태 정보들이 초기화되기 때문에 이전의 오프라인 백업 파일들이 가지고 있는 상태정보와 일치될 수 없기 때문 입니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] cd c:\oracle\oradata\ora92 [C:\] copy *.* c:\backup [C:\] copy c:\oracle\ora92\database\init.ora c:\backup → 관련된 모든 데이터 파일, 컨트롤 파일, 리두로그 파일, 파라메터 파일들을 오프라인 백업 하십시오. [C:\] del c:\oracle\oradata\ora92\arch\*.arc → 불완전 복구에 의해 데이터베이스의 모든 상태 정보들이 초기화되면 이전까지 생성 되었던 아카이브 파일들도 이젠 더 이상 필요 없는 파일들이 됩니다. 아카이브 파일들은 사용 가능한 마지막 오프라인 백업파일 이후에 생성된 것 들만 사용 가능하므로 초기화된 현재 시점에서는 이전의 아카이브 파일은 사용될 수 없습니다.
5-1-2 취소기반 불완전 복구

이번에는 불완전 복구의 두 번째 방법인 취소기반 복구방법에 대해서 알아 보도록 하겠습니다. 대부분의 기업환경에서 데이터베이스에 장애가 발생하면 장애가 발생한 시점까지의 모든 데이터를 안전하게 복구하는 것이 원칙일 것 입니다. 하지만, 백업 데이터 파일과 아카이브 파일의 보관 및 관리 상의 문제로 인해 복구를 정상적으로 수행하지 못하는 경우도 때로는 발생하게 됩니다. 이런 경우에는 사용 가능한 백업 데이터를 이용하여 복구할 수 있는 시점까지 만이라고 최대한 복구작업을 수행해야 할 것 입니다. 
바로 이런 경우의 복구방법을 취소기반 불완전 복구라고 합니다.

위 그림에서, 현재 시점 2001년 6월 10일 오전 12시에 데이터베이스를 종료한 후 오프라인 백업을 통해 SCN 번호가 95인 모든 파일(데이터 파일, 컨트롤 파일, 리두로그 파일)들을 백업하고 있습니다. 현재, 데이터베이스는 아카이브 모드이며, 오프라인 백업 이후 발생한 모든 트랜잭션 데이터들은 아카이브 파일과 리두로그 파일에 기록되어 있습니다. 
ARC1.LOG, ARC2.LOG, ARC3.LOG 파일에 모든 백업 데이터들이 저장되었다고 합니다. 
현재시점, 2001년 6월 12일 오후 13시, 시스템 관리자가 실수로 USERS01.DBF 데이터 파일을 삭제했다고 합니다. 이 사실을 모른체 사용자들은 해당 데이터 파일에 저장되어 있는 테이블에 대해 입력, 수정, 삭제작업을 수행하려고 합니다. 하지만, 이 시점에 해당 디크크에는 USERS01.DBF 파일은 존재하지 않기 때문에 사용자들은 더 이상 데이터베이스를 사용할 수 없게 됩니다. 문제는, 이 데이터 파일에 대한 복구 작업을 수행하기 위해 복구작업 시 사용되어야 할 모든 아카이브 파일들 중에 몇 개가 유실되어 사용될 수 없다고 합니다.


사례-8

어느 날, 모든 리두로그 파일이 존재하는 디스크에 장애가 발생했다고 합니다. 현재 데이터베이스는 아카이브 모드이며 최근에 전체 데이터베이스 백업이 수행되었다고 합니다. 

장애가 발생한 시점까지의 모든 데이터는 복구할 수 있을까요 ? 

결론적으로 말씀드리면, 마지막 백업 데이터가 저장되어 있던 온라인 리두로그 파일이 아카이브 되지 않은 상태에서 유실되었기 때문에 완전복구 작업은 수행할 수 없는 상태입니다. 
즉, 불완전 복구작업을 수행해야 합니다.


(1) 오라클 서버가 사용 가능한 상태인지 확인하고 MOREDEPT.SQL을 실행한 후 아카이브 파일들이 정상적으로 생성되는지 확인하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup SQL> @moredept.sql alter system switch logfile; insert into scott.dept values(1,'Personnel','Pusan'); insert into scott.dept values(2,'Account','Pusan'); insert into scott.dept values(3,'Q.C','Pusan'); alter system switch logfile; insert into scott.dept values(4,'Personnel','Seoul'); insert into scott.dept values(5,'Account','Seoul'); insert into scott.dept values(6,'Q.C','Seoul'); alter system switch logfile; insert into scott.dept values(7,'Personnel','Daejeon'); insert into scott.dept values(8,'Account','Daejeon'); insert into scott.dept values(9,'Q.C','Daejeon'); commit; select count(*) from scott.dept;

(2) 이번 시나리오는 여러 개의 리두로그 파일들 중에 LGWR 프로세스에 의해 현재 쓰여지고 있는 CURRENT 리두로그 파일에 장애가 발생한 경우 복구하는 방법과 절차를 소개합니다. 먼저, 현재 사용하고 있는 오라클 서버에서 CURRENT 상태의 리두로그 파일을 확인하십시오. 그리고, CURRENT 리두로그 파일을 삭제하여 장애가 발생한 시나리오를 만들어 보시기 바랍니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> select member from v$log where status = 'CURRENT'; MEMBER --------------------------------------------------- c:\oracle\oradata\ora92\redo01.log → 만약, 현재 데이터베이스에서 REDO01.LOG 파일이 CURRENT 상태의 리두로그 파일이 라면 다음과 같이 화면에 출력됩니다. SQL> host dir c:\oracle\oradata\ora92 SQL> host del c:\oracle\oradata\ora92\redo01.log → Windows 환경의 운영체계에서는 서버에 의해 삭제가 안됩니다. SQL> host del c:\oracle\oradata\ora92\redo01b.log → Windows 환경의 운영체계에서는 서버에 의해 삭제가 안됩니다. SQL> host dir c:\oracle\oradata\ora92 SQL> @moredept.sql → 온라인 리두로그 파일이 유실되었기 때문에 에러가 발생합니다. 또는, 무한정 대기상태에 빠지게 되기도 합니다. SQL> shutdown abort → 에러가 발생하는 경우에는 오라클 서버가 자동 종료됩니다. 경우에 따라서는 무한정 대기상태에 빠지기도 하는데 이런 경우에는, 정상적인 복구작업을 수행하기 위해서 강제로 오라클 서버를 종료 시켜야 합니다. 바로 이때, SHUTDOWN 명령어의 ABORT 옵션을 이용하시면 오라클 서버를 강제 종료 시킬 수 있습니다.

(3) 자~ 그럼, CURRENT 리두로그 파일이 유실된 경우 불완전 복구를 수행해 봅시다. 
오라클 서버가 자동 종료되었거나, ABORT 옵션에 의해 강제 종료된 다음 다시 오라클 서버를 MOUNT 단계까지 만 시작한 다음 불완전 복구를 수행하기 위해 마지막 오프라인 백업 파일들 중에 모든 데이터 파일들 만 재 설치합니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> startup SQL> alter database drop logfile group 그룹번호; → 일반적으로 INACTIVE 리두로그 파일이 유실된 경우에는 관련 리두로그 파일을 제거한 후 다시 재 생성함으로써 복구작업을 완료할 수 있었습니다. 같은 방법으로 복구가 가능한지 수행해 보십시오. 하지만, CURRENT 리두로그 파일은 ALTER DATABASE DROP LOGFILE~ 명령어로는 더 이상 삭제할 수 없습니다. 왜냐하면, CURRENT 상태의 리두로그는 현재 쓰여지고 있는 파일을 의미하기 때문에 데이터베이스 관리자도 삭제할 수 없기 때문 입니다. SQL> shutdown immediate SQL> exit

(4) 다음은 정상적인 불완전 복구를 수행하는 방법과 절차입니다. 
먼저, 현재 생성되어 있는 마지막 아카이브 파일이 몇 번인지 확인해 두십시오. 다음과 같이 여러 가지 방법을 통해 확인할 수 있습니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>첫 번째 방법은 ALERT 파일의 로그 내용을 분석해 보면 마지막 아카이브 파일의 번호를 알아 낼 수 있습니다. [C:\] cd c:\oracle\admin\ora92\bdump [C:\] dir [C:\] edit ALERT_<db>명>.log → 파일의 끝부분으로 이동해서 Archiving을 실패한 기록과 Sequence 번호 확인 예를 들어, ORA-00255: error archiving log 1 of thread 1, sequence # 15 sequence # 15번이라면 마지막 아카이브 파일번호가 15번 입니다. 두 번째 방법은 아카이브 파일이 생성되어 있는 경로로 이동하여 마지막 파일 번호를 확인하는 방법입니다. [C:\] DEL C:\ORACLE\ORA92\DATABASE\ARCH [C:\] dir</db명>

(5) 이전에 마지막으로 오프라인 백업된 파일들 중에 모든 데이터 파일들만 재설치하십시오. 컨트롤 파일과 리두로그 파일들은 재 설치할 필요가 없습니다. 모든 파일들을 재 설치하게 되면 완전복구 방법이 되며, 데이터 파일들 만 설치하면 불완전 복구가 됩니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] cd c:\backup [C:\] copy *.dbf c:\oracle\oradata\ora92 [C:\] sqlplus "/as sysdba" SQL> startup mount SQL> recover database until cancel ORA-00279: Change 7220 generated at 02/24/97 23:51:30 needed ORA-00289: Suggestion : c:\oracle\oradata\ora92\arch\arch_1.arc ORA-00280: Change 7220 for thread 1 is in sequence #1 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} Enter ← 1번 아카이브 파일을 적용해 줍니다. ORA-00279: Change 7220 generated at 02/24/97 23:51:30 needed ORA-00289: Suggestion : c:\oracle\oradata\ora92\arch\arch_2.arc ORA-00280: Change 7220 for thread 1 is in sequence #2 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} Enter ← 2번 아카이브 파일을 적용해 줍니다. ………………………….. ORA-00279: Change 7220 generated at 02/24/97 23:51:30 needed ORA-00289: Suggestion : c:\oracle\oradata\ora92\arch\arch_15.arc ORA-00280: Change 7220 for thread 1 is in sequence #15 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} Enter ← 15번 아카이브 파일을 적용해 줍니다. ORA-00279: Change 7220 generated at 02/24/97 23:51:30 needed ORA-00289: Suggestion : c:\oracle\oradata\ora92\arch\arch_16.arc ORA-00280: Change 7220 for thread 1 is in sequence #16 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} CANCEL ← 아카이브 파일을 적용하기 전에 현재 시점까지 생성되어 있는 마지막 아카이브 파일이 15번까지 생성되어 있는 것을 확인하였습니다. 그렇다면, 16번 아카이브 파일은 존재하지 않으므로 더 이상 복구작업을 수행할 수 없습니다. CANCEL을 입력하면 복구작업은 중단됩니다. Media Complete Cancel. ← 불완전 복구작업이 완료되었습니다. SQL> alter database open resetlogs; → 불완전 복구는 데이터베이스의 모든 상태가 불 일치하기 때문에 복구작업을 완료한 후 반드시 RESETLOGS 옵션을 사용하여 OPEN 해야 합니다. 이 명령어를 실행하면 유실된 모든 리두로그 파일들이 자동으로 생성됩니다. SQL> archive log list 데이터베이스 로그모드 아카이브 모드 가장 오래된 온라인 로그순서 1 ← 모든 상태정보가 초기화 된 것을 확인하십시오. 아카이브할 다음 로그 1 현재 로그순서 1 SQL> shutdown immediate SQL> exit</ret></ret></ret></ret>

(6) 데이터베이스의 모든 상태정보가 초기화되는 불완전 복구방법이 수행되고 나면 마지막으로 백업되었던 백업파일은 더 이상 사용할 수 없으므로 반드시 오프라인 백업을 수행해야 합니다. 또한, 오프라인 백업이 수행되고 나면 이전의 모든 트레이스 파일와 로그 파일, 아카이브 파일들을 삭제하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] cd c:\oracle\oradata\ora92 [C:\] copy *.* c:\backup [C:\] copy c:\oracle\ora92\database\init.ora c:\backup [C:\] del c:\oracle\admin\ora92\udump\*.trc [C:\] del c:\oracle\admin\ora92\bdump\alert_<db>명>.log [C:\] cd c:\oracle\ora92\database\arch [C:\] del *.arc [C:\] dir</db명>
사례-9

데이터베이스의 컨트롤 파일이 존재하는 디스크에 장애가 발생하여 더 이상 입력, 수정, 삭제 작업을 수행할 수 없습니다. 모든 컨트롤이 유실된 상태이며 마지막으로 백업된 컨트롤 파일 만이 사용 가능한 상태입니다. 어떻게 복구해야 할까요 ?


(1) 오라클 서버가 사용 가능한 상태인지 확인하고 MOREDEPT.SQL을 실행한 후 아카이브 파일들이 정상적으로 생성되는지 확인하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup SQL> @moredept alter system switch logfile; insert into scott.dept values(1,'Personnel','Pusan'); insert into scott.dept values(2,'Account','Pusan'); insert into scott.dept values(3,'Q.C','Pusan'); alter system switch logfile; insert into scott.dept values(4,'Personnel','Seoul'); insert into scott.dept values(5,'Account','Seoul'); insert into scott.dept values(6,'Q.C','Seoul'); alter system switch logfile; insert into scott.dept values(7,'Personnel','Daejeon'); insert into scott.dept values(8,'Account','Daejeon'); insert into scott.dept values(9,'Q.C','Daejeon'); commit; select count(*) from scott.dept; SQL> host dir c:\oracle\ora92\database\arch\*.arc

(2) 이번 사례는 데이터베이스의 모든 상태정보와 오라클 서버의 시작과 종료 시 반드시 필요한 컨트롤 파일에 대한 내용입니다. 
여러 개의 컨트롤 파일 중 하나라도 장애가 발생하면 더 이상 오라클 서버를 사용할 수 없기 때문에 오라클 데이터베이스 구조 중에 가장 중요한 파일 중에 하나입니다. 
먼저, 현재 사용하고 있는 오라클 서버에서 컨트롤 파일의 위치와 개수를 확인하십시오. 그리고, 모든 컨트롤 파일을 삭제하여 장애가 발생한 시나리오를 만들어 보시기 바랍니다.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> shutdown abort --> 오라클 서버가 비정상적으로 종료됩니다. SQL> exit [C:\] del c:\oracle\oradata\ora92\*.ctl ← 사용자의 실수로 인해 모든 컨트롤 파일이 삭제됩니다. (실제 기업환경에서는 임의로 컨트롤 파일을 삭제해서는 안됩니다.)

(3) 결론적으로 모든 컨트롤 파일에 장애가 발생하면 더 이상 오라클 데이터베이스를 사용할 수 없게 됩니다. 이런 현상이 발생하는 경우에는 불완전 복구방법을 사용합니다. 
마지막 오프라인 백업된 백업 파일로부터 모든 컨트롤 파일을 현재 경로로 재 설치하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\]copy c:\backup\*.ctl c:\oracle\oradata\ora92\*.ctl [C:\] sqlplus "/as sysdba" SQL> startup mount SQL> recover database using BACKUP controlfile ← 현재 환경은 컨트롤 파일 만 이전의 백업 파일이고 다른 파일들은 현재 시점의 파일들이기 때문에 컨트롤 파일 만의 복구작업을 수행하기 위해 USING BACKUP CONTROLFILE 절을 사용하여 복구작업을 수행해야 합니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed for thread 1 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} C:\oracle\oradata\ora92\arch\arch_1.arc ← 만약, 적용해야 할 아카이브 파일이 지정되지 않으면 직접 첫 번째 아카이브 파일의 경로와 이름을 입력해야 합니다. 적용해야 할 아카이브 파일명이 출력 되는 경우에는 AUTO 키워드를 입력하여 자동으로 아카이브를 적용하시면 됩니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed ORA-00280: Change 8050 for thread 1 is in sequence arch_2.arc Specify log: {<ret>=suggested | filename | AUTO | CANCEL} AUTO ← 첫 번째 아카이브를 적용하면 두 번째 아카이브 파일의 이름과 경로가 출력되고 해당 파일을 적용할 것 인지가 나타납니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed ORA-00280: Change 8050 for thread 1 is in sequence arch_n.arc ← 여러 개의 아카이브 파일을 적용하다 마지막 아카이브 파일을 적용하려고 했을 때 에러가 발생할 수 도 있습니다. 이런 경우는 적용해야 할 마지막 백업 데이터가 아카이브 파일로 저장되어 있는 것이 아니라, CURRENT 리두로그 파일에 저장되어 있기 때문입니다. 이러 경우에는 마지막 CURRENT 리두로그 파일의 경로와 이름을 지정해 주시면 됩니다. SQL> recover database using BACKUP controlfile 에러가 발생하면 다시 리두로그 파일을 적용해 줄 수 없으므로 RECOVER DATABASE 명령어를 재 수행하시면 됩니다. ORA-00279: Change 8050 generated at 01/20/98 15:22:26 needed ORA-00280: Change 8050 for thread 1 is in sequence arch_n.arc Specify log: {<ret>=suggested | filename | AUTO | CANCEL} c:\oracle\oradata\ora92\redo01.log --> 마지막 CURRENT 리두로그 파일명을 입력하십시오 Log applied. Media recovery complete. SQL> alter database open resetlogs; ← 절차와 방법은 완전복구 방법과 같지만 결론적으로 이 방법은 불완전 복구입니다. 왜냐하면, 데이터베이스의 모든 상태정보가 저장되어 있는 컨트롤 파일이 삭제되었 기 때문에 컨트롤 파일은 복구되었지만 상태정보는 복구되지 않았기 때문입니다. SQL> select count(*) from scott.dept; --> 정상적으로 검색이 가능합니다. SQL> shutdown SQL> exit</ret></ret></ret>

(4) 불완전 복구를 수행하고 나면 반드시 이전의 마지막 백업파일은 재 사용될 수 없기 때문에 다시 오프라인 백업을 수행해야 합니다. 또한, 이전의 아카이브 파일, 트레이스 파일들도 제거 하십시오.

<xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] cd c:\oracle\oradata\ora92 [C:\] copy *.* c:\backup [C:\] copy c:\oracle\ora92\database\init.ora c:\backup

 

Posted by redkite
, |

오라클 사에서 제공하는 완전복구 방법에 대해 소개하기 전에 데이터베이스 관리자로써 장애와 복구에 대한 전반적인 내용을 이해하고 장애가 발생한 경우 효과적으로 복구작업을 수행하기 위해서 반드시 준비하셔야 할 내용이 있습니다. 
그것은 바로, 여러분들이 관리하고 계시는 오라클 데이터베이스의 모든 파일에 대한 구조와 시스템에 대한 기본적인 정보입니다. 
데이터베이스 관리자가 평소에 얼마나 정확하게 자신이 관리하고 있는 데이터베이스의 물리적 구조를 잘 이해하느냐는 장애 발생 시 얼마나 빠르고 효과적으로 데이터베이스를 복구할 수 있느냐를 결정하는 첫 번째 기준이 됩니다.

 

4장 OFF-Line 백업을 이용한 완전복구

  4-1 데이터베이스의 구조분석

먼저, 오라클 사에서 제공하는 완전복구 방법에 대해 소개하기 전에 데이터베이스 관리자로써 장애와 복구에 대한 전반적인 내용을 이해하고 장애가 발생한 경우 효과적으로 복구작업을 수행하기 위해서 반드시 준비하셔야 할 내용이 있습니다.

그것은 바로, 여러분들이 관리하고 계시는 오라클 데이터베이스의 모든 파일에 대한 구조와 시스템에 대한 기본적인 정보입니다.

데이터베이스 관리자가 평소에 얼마나 정확하게 자신이 관리하고 있는 데이터베이스의 물리적 구조를 잘 이해하느냐는 장애 발생 시 얼마나 빠르고 효과적으로 데이터베이스를 복구할 수 있느냐를 결정하는 첫 번째 기준이 됩니다.

다음은 오라클 데이터베이스의 모든 물리적 구조정보를 분석하는 방법입니다.


1) 현재 생성되어 있는 모든 물리적 구조를 분석한 다음 그 정보를 파일로 생성하십시오.
<xmp></xmp>[C:\] sqlplus "/as sysdba" SQL> SPOOL oracle_files.dat - 먼저, 모든 데이터 파일의 구조를 분석하십시오. <xmp></xmp>SQL> COL TABLESPACE_NAME FORMAT A15 SQL> COL FILE_NAME FORMAT A50 SQL> SELECT file_id, file_name, tablespace_name FROM dba_data_files; FILE_ID FILE_NAME TABLESPACE_NAME -------- ------------------------------------- --------------- 1 C:\ORACLE\ORADATA\ORA92\SYSTEM01.DBF SYSTEM 2 C:\ORACLE\ORADATA\ORA92\UNDOTBS.DBF UNDOTBS 3 C:\ORACLE\ORADATA\ORA92\TEMP01.DBF TEMP 4 C:\ORACLE\ORADATA\ORA92\USERS01.DBF USERS- 다음은, 모든 컨트롤 파일의 구조를 분석하십시오. <xmp></xmp>SQL> COL NAME FORMAT A50 SQL> SELECT * FROM v$controlfile; STATUS NAME ------------------------------------------------ C:\ORACLE\ORADATA\ORA92\CONTROL01.CTL C:\ORACLE\ORADATA\ORA92\CONTROL02.CTL C:\ORACLE\ORADATA\ORA92\CONTROL03.CTL- 마지막으로, 모든 리두로그 파일의 구조를 분석하십시오. <xmp></xmp>SQL> COL MEMBER FORMAT A50 SQL> SELECT * FROM v$logfile; GROUP# STATUS TYPE MEMBER ---------- --------- ------ ---------------------------------- 1 ONLINE C:\ORACLE\ORADATA\ORA92\REDO01.LOG 2 ONLINE C:\ORACLE\ORADATA\ORA92\REDO02.LOG 3 ONLINE C:\ORACLE\ORADATA\ORA92\REDO03.LOG SQL> SPOOL OFF ← 운영체계 상에 ORACLE_FILE.DAT 파일이 생성됩니다. SQL> EXIT [C:\] EDIT ooracle_files.dat ← 저정된 물리적 구조정보를 참조할 수 있습니다.

4-2 완전복구 방법
4-2-1 전체 완전 복구

아카이브 모드 환경에서 데이터베이스에 장애가 발생하면 2가지 방법으로 복구작업을 수행할 수 있습니다. 첫 번째 방법은 완전 복구(Complete Recovery) 이며, 두 번째 방법은 불완전 복구(InComplete Recovery) 입니다.

장애가 발생한 시점에 어떤 복구 방법에 의해 데이터베이스를 복구할 것인지를 결정하는 것은 장애의 발생상태 및 복구 전략에 따라 선별적으로 사용할 수 있습니다.

예를 들어, 장애가 발생한 상태를 확인했을 때, 데이터 파일 만 문제가 생긴 경우와 데이터 파일과 리두로그 파일 모두에 문제가 발생한 경우에 복구 방법은 달라질 수 있다는 것 입니다. 또는, 오라클 데이터베이스를 구성하는 파일구조에 문제가 발생한 것이 아니라, 특정 테이블을 사용자가 실수에 의해 DROP 한 경우 복구 방법은 달라질 수 있습니다.

결론적으로, 장애가 발생한 시점에 먼저, 장애 원인을 정확하게 분석할 수 있어야 하며, 그 결과에 따라 적절한 복구 방법을 선택해야 한다는 것 입니다.

이러한 과정을 통해 장애 복구를 원활하게 수행하기 위해서는 오라클 서버의 구조를 완벽하게 이해해야 하며, 또한 각각의 복구 방법과 절차에 대한 명확한 이해와 장단점을 잘 알고 있어야 합니다.

자 ~ 그럼 아카이브 모드에서 수행할 수 있는 완전복구에 대해 보다 자세히 알아 봅시다.

완전복구(Complete Recovery)는 데이터베이스에 장애가 발생한 경우 마지막으로 수행한 오프라인 백업 데이터와 그 이후 생성된 아카이브 파일 그리고 아카이브 되지 않은 현재 시점의 백업 데이터를 저장하고 있는 리두로그 파일을 통해 장애가 발생한 시점까지의 모든 데이터를 완전하게 복구하는 방법입니다.

위 그림에서, 현재시점 2001년 6월 10일 오전 12시에 데이터베이스를 종료한 후 오프라인 백업을 통해 SCN 번호가 95인 모든 파일(데이터 파일, 컨트롤 파일, 리두로그 파일)들을 백업하고 있습니다. 현재, 데이터베이스는 아카이브 모드이며, 오프라인 백업 이후 발생한 모든 트랜잭션 데이터들은 아카이브 파일과 리두로그 파일에 기록되어 있습니다.

첫 번째 아카이브 파일 ARC1.LOG 에는 마지막 오프라인 백업 이후부터 2001년 6월 11일 오전 12시까지의 백업 데이터들이 저장 되었다고 합니다.

그리고, 두 번째 아카이브 파일 ARC2.LOG 에는 2001년 6월 11일 오전 12시부터 2001년 6월 12일 오전 12시까지의 백업 데이터들이 저장되었으며, 2001년 6월 12일 오전 12시부터 6월 12일 오후 13시까지의 데이터들은 ARC3.LOG 파일에 기록되어 있다고 합니다.

현재 시점, 2001년 6월 12일 오후 13시에 USERS01.DBF 데이터 파일이 저장되어 있는 디스크에 장애가 발생하여 더 이상 데이터베이스를 사용할 수 없다고 합니다.


사례-4.

아카이브 모드에서 DB 내의 특정 데이터 파일들이 장애가 발생하여 더 이상 입력, 수정, 삭제 작업을 수행할 수 없다고 합니다. 다행히 최근에 백업된 데이터 파일들과 아카이브 파일들은 정상적으로 사용 가능한 상태라고 합니다. 전체 데이터베이스 완전 복구를 수행해 보도록 하겠습니다.


1) 오라클 서버가 사용 가능한 상태인지 확인하고 아카이브 파일들이 정상적으로 생성되는지 확인하십시오. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup SQL> host dir c:\oracle\oradata\ora92\arch\*.arc → 현재, 아카이브 파일의 개수와 마지막 아카이브 파일번호를 메모해 두십시오. SQL> host more moredept.sql alter system switch logfile; insert into scott.dept values(1,'Personnel','Pusan'); insert into scott.dept values(2,'Account','Pusan'); insert into scott.dept values(3,'Q.C','Pusan'); alter system switch logfile; insert into scott.dept values(4,'Personnel','Seoul'); insert into scott.dept values(5,'Account','Seoul'); insert into scott.dept values(6,'Q.C','Seoul'); alter system switch logfile; insert into scott.dept values(7,'Personnel','Daejeon'); insert into scott.dept values(8,'Account','Daejeon'); insert into scott.dept values(9,'Q.C','Daejeon'); commit; select count(*) from scott.dept; → 이 스크립트를 실행하면 아카이브 파일들이 생성됩니다. SQL> @moredept.sql SQL> shutdown immediate SQL> exit [C:\] dir c:\oracle\oradata\ora92\arch\*.arc → MOREDEPT.SQL을 실행한 후 아카이브 파일이 몇 개 추가생성 되었는지 확인하십시오.
2) 이 사례를 위해 USERS01.DBF 파일을 삭제한 후 오라클 서버를 다시 시작해 보십시오. OPEN 단계에서 파일의 삭제로 인해 데이터베이스의 무결성이 보장되지 않아 에러가 발생할 것 입니다. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\]dir c:\oracle\oradata\ora92\*.dbf → USERS 테이블스페이스를 구성하는 데이터 파일 [C:\]del c:\oracle\oradata\ora92\users01.dbf → 해당 파일이 존재하는 디스크에 장애가 발생한 것으로 시나리오를 만듭니다. [C:\] dir c:\oracle\oradata\ora92\*.dbf [C:\] sqlplus "/as sysdba" SQL> startup ORA-01157 데이터 9파일을 식별 또는 잠금할 수 없습니다-DBWR 추적파일을 보십시오 ORA-01110 : 9 데이터 파일: C:\ORALCE\ORADATA\ORA92\USERS01.DBF SQL> shutdown SQL> exit
3) 이전에 받은 전체 오프라인 백업파일로부터 손상된 데이터 파일들을 재설치 한 후 전체 완전복구 방법으로 복구작업을 수행합니다. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\]cd c:\backup [C:\] dir [C:\]copy users01.dbf c:\oracle\oradata\ora92\users01.dbf [C:\]sqlplus "/as sysdba" SQL> startup Database mounted. ORA-01113: 9 파일이 매체 복구되어야 합니다. ORA-01110: 9 데이터 파일: C:\ORALCE\ORADATA\ORA92\USERS01.DBF SQL> SELECT * FROM V$RECOVER_FILE; FILE# ONLINE ERROR CHANGE# --------------------------------------------- 9 ONLINE 406577 SQL> recover database ORA-00279: Change 7474 generated at 04/24/97 22:52:31 ORA-00289: Suggestion : c:\oracle\oradata\ora92\arch\arch_256.arc ORA-00280: Change 7474 for thread 1 is in sequence #256 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} AUTO ← AUTO를 입력한 후 Enter를 누르면 모든 아카이브 파일들을 자동으로 적용해줍니다. Media recovery complete. → 정상적으로 복구작업이 완료되면 반드시 이 메시지가 출력됩니다. SQL> alter database open; → 현재 오라클 서버는 마운트 상태이므로 OPEN 합니다.</ret>
4) 오라클 데이터베이스가 정상적으로 복구 되었는지 확인해 보십시오. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>SQL> select count(*) from scott.DEPT; SQL> shutdown immediate SQL> exit
4-2-2 테이블스페이스 완전복구

이번에는, 완전복구(Complete Recovery) 3가지 방법 중에 테이블스페이스 완전복구에 대해 알아 보도록 하겠습니다. 전체 완전복구는 MOUNT 단계에서 모든 데이터 파일을 대상으로 복구작업을 수행하는 방법이라면, 테이블스페이스 완전복구는 OPEN 단계에서, 장애가 발생한 데이터 파일의 테이블스페이스를 기준으로 복구 작업을 수행하게 됩니다.

위 그림에서, 현재시점 2001년 6월 10일 오전 12시에 데이터베이스를 종료한 후 오프라인 백업을 통해 SCN 번호가 95인 모든 파일(데이터 파일, 컨트롤 파일, 리두로그 파일)들을 백업하고 있습니다. 현재, 데이터베이스는 아카이브 모드이며, 오프라인 백업 이후 발생한 모든 트랜잭션 데이터들은 아카이브 파일과 리두로그 파일에 기록되어 있습니다.

ARC1.LOG, ARC2.LOG, ARC3.LOG 파일에 모든 백업 데이터들이 저장되었다고 합니다.

현재시점, 2001년 6월 12일 오후 13시에 USERS01.DBF 데이터 파일이 저장되어 있는 디스크에 장애가 발생하여 더 이상 관련 테이블스페이스를 사용할 수 없다고 합니다.


사례-5.

아카이브 모드에서 DB 내의 특정 데이터 파일들이 장애가 발생하여 더 이상 입력, 수정, 삭제 작업을 수행할 수 없다고 합니다. 다행히 최근에 백업된 데이터 파일들과 아카이브 파일들은 정상적으로 사용 가능한 상태라고 합니다. 그리고, 문제가 발생한 데이터 파일은 특정 테이블스페이스에 포함된 데이터 파일이라고 합니다.

이런 경우, 데이터베이스 전체를 대상으로 복구작업을 수행하게 되면 많은 시간이 소요될 수 있으므로 테이블스페이스 완전 복구방법을 수행해 보도록 하겠습니다.


1) 오라클 서버가 사용 가능한 상태인지 확인하고 아카이브 파일들이 정상적으로 생성되는지 확인하십시오. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup SQL> host dir c:\oracle\ora92\database\arch\*.arc → 현재, 생성되어 있는 아카이브 파일의 개수 및 마지막 파일명을 메모해 두십시오. SQL> host more moredept.sql alter system switch logfile; insert into scott.dept values(1,'Personnel','Pusan'); insert into scott.dept values(2,'Account','Pusan'); insert into scott.dept values(3,'Q.C','Pusan'); alter system switch logfile; insert into scott.dept values(4,'Personnel','Seoul'); insert into scott.dept values(5,'Account','Seoul'); insert into scott.dept values(6,'Q.C','Seoul'); alter system switch logfile; insert into scott.dept values(7,'Personnel','Daejeon'); insert into scott.dept values(8,'Account','Daejeon'); insert into scott.dept values(9,'Q.C','Daejeon'); commit; select count(*) from scott.dept; SQL> @moredept.sql SQL> shutdown immediate SQL> exit [C:\]dir c:\oracle\ora92\database\arch\*.arc → MOREDEPT.SQL을 실행한 후 생성된 아카이브 파일의 개수와 마지막 파일명을 메모해 두십시오.
2) 이 실습을 위해 USERS01.DBF 파일을 삭제한 후 오라클 서버를 재 시작해 보십시오. OPEN 단계에서 해당 파일이 존재하지 않으므로 에러가 발생할 것 입니다. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\]dir c:\oracle\oradata\ora92\*.dbf → USERS 테이블스페이스를 구성하고 있는 데이터 파일명을 확인하십시오. [C:\]del c:\oracle\oradata\ora92\users01.dbf → 이 실습을 위해 해당 파일을 삭제합니다. [C:\] dir c:\oracle\oradata\ora92\*.dbf [C:\] sqlplus "/as sysdba" SQL> startup ORA-01157 데이터 9파일을 식별 또는 잠금할 수 없습니다-DBWR 추적파일을 보십시오 ORA-01110 : 9 데이터 파일: C:\ORALCE\ORADATA\ORA92\USERS01.DBF SQL> shutdown SQL> exit
3) 이전에 수행된 전체 오프라인 백업 파일들로부터 손상된 USERS01.DBF 파일을 재설치한 후 테이블스페이스 완전복구 방법을 이용한 복구작업을 수행하십시오, <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\]cd c:\backup [C:\]dir [C:\]copy users01.dbf c:\oracle\oradata\ora92\users01.dbf [C:\]sqlplus "/as sysdba" SQL> startup Database mounted. ORA-01113: 9 파일이 매체 복구되어야 합니다. ORA-01110: 9 데이터 파일: C:\ORALCE\ORADATA\ORA92\USERS01.DBF SQL> SELECT * FROM V$RECOVER_FILE; FILE# ONLINE ERROR CHANGE# ------ ----------- ------------- ------------ 9 ONLINE 406577 SQL> select FILE#, STATUS, NAME from v$datafile; ← USERS01.DBF 파일의 상태는 ONLINE SQL> alter database datafile 'c:\oracle\oradata\ora92\users01.dbf' offline; SQL> select FILE#, STATUS, NAME from v$datafile; ← USERS01.DBF 파일의 상태는 OFFLINE SQL> alter database open; SQL> select TABLESPACE_NAME, STATUS from dba_tablespaces; TABLESPACE_NAME STATUS ----------------------- -------------------------- USERS ONLINE SQL> alter tablespace users offline immediate; SQL> select TABLESPACE_NAME, STATUS from dba_tablespaces; TABLESPACE_NAME STATUS ------------------------ ------------------------ USERS OFFLINE SQL> recover tablespace users ORA-00279: Change 7220 generated at 02/24/97 23:51:30 ORA-00289: Suggestion : /DBAX/DBA805/dba숫자/arch_219.arc ORA-00280: Change 7220 for thread 1 is in sequence #219 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} AUTO → 관련된 모든 아카이브 파일들을 자동 적용해 줍니다. SQL> select count(*) from scott.dept; ← 에러 발생, 복구는 되었지만 offline 상태 ORA-00376: 현재 파일 9를 읽을 수 없습니다. ORA-01110: 9 데이터 파일 SQL> alter tablespace users online; SQL> select count(*) from scott.dept; → 정상적으로 수행 됨 SQL> shutdown immediate SQL> exit</ret>
4-2-3 데이터 파일 완전복구

이번에는, 완전복구의 마지막 방법 인 데이터 파일 완전복구 방법을 소개하도록 하겠습니다.

위 그림에서, 현재시점 2001년 6월 10일 오전 12시에 데이터베이스를 종료한 후 오프라인 백업을 통해 SCN 번호가 95인 모든 파일(데이터 파일, 컨트롤 파일, 리두로그 파일)들을 백업하고 있습니다. 현재, 데이터베이스는 아카이브 모드이며, 오프라인 백업 이후 발생한 모든 트랜잭션 데이터들은 아카이브 파일과 리두로그 파일에 기록되어 있습니다. 
ARC1.LOG, ARC2.LOG, ARC3.LOG 파일에 모든 백업 데이터들이 저장되었다고 합니다. 
현재시점, 2001년 6월 12일 오후 13시에 USERS01.DBF 데이터 파일이 저장되어 있는 디스크에 장애가 발생하여 더 이상 관련 파일을 사용할 수 없다고 합니다.


사례-6

아카이브 모드에서 DB 내에 특정 데이터 파일들이 장애가 발생하여 더 이상 입력, 수정, 삭제 작업을 수행할 수 없다고 합니다. 다행히 최근에 백업된 데이터 파일들과 아카이브 파일들은 정상적으로 사용 가능한 상태라고 합니다. 현재, 장애가 발생한 데이터 파일은 하나의 데이터 파일이라고 합니다. 
이런 경우, 전체 데이터베이스 또는 특정 테이블스페이스 완전 복구방법을 수행하게 되면 불필요한 복구 시간이 소요될 수 있으므로 이번에는 데이터 파일 완전 복구 방법을 수행해 보도록 하겠습니다.


1) 오라클 서버가 사용 가능한 상태인지 확인하고 아카이브 파일들이 정상적으로 생성되는지 확인하십시오. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] sqlplus "/as sysdba" SQL> startup SQL> host dir c:\oracle\ora92\database\arch\*.arc → 현재 생성되어 있는 아카이브 파일의 개수와 마지막 파일명을 메모해 두십시오. SQL> host more moredept.sql alter system switch logfile; insert into scott.dept values(1,'Personnel','Pusan'); insert into scott.dept values(2,'Account','Pusan'); insert into scott.dept values(3,'Q.C','Pusan'); alter system switch logfile; insert into scott.dept values(4,'Personnel','Seoul'); insert into scott.dept values(5,'Account','Seoul'); insert into scott.dept values(6,'Q.C','Seoul'); alter system switch logfile; insert into scott.dept values(7,'Personnel','Daejeon'); insert into scott.dept values(8,'Account','Daejeon'); insert into scott.dept values(9,'Q.C','Daejeon'); commit; select count(*) from scott.dept; SQL> @moredept.sql SQL> shutdown immediate SQL> exit [C:\]dir c:\oracle\ora92\database\arch\*.arc → MOREDEPT.SQL을 실행한 후 추가 생성된 아카이브 파일의 개수와 마지막 파일명을 메모해 두십시오.
2) 이 실습예제를 수행하기 위해 USERS01.DBF 파일을 삭제한 후 오라클 서버를 다시 시작해 보십시오. 해당 파일이 더 이상 존재하지 않기 때문에 OPEN 단계에서 에러가 발생할 것 입니다. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\]dir c:\oracle\oradata\ora92\*.dbf → USERS 테이블스페이스가 구성하는 테이터 파일을 확인하십시오. [C:\]del c:\oracle\oradata\ora92\users01.dbf → 실습 시나리오를 위해 USERS01.DBF 파일을 삭제하십시오. [C:\] dir c:\oracle\oradata\ora92\*.dbf [C:\] sqlplus "/as sysdba" SQL> startup ORA-01157 데이터 9파일을 식별 또는 잠금할 수 없습니다-DBWR 추적파일을 보십시오 ORA-01110 : 9 데이터 파일: C:\ORALCE\ORADATA\ORA92\USERS01.DBF SQL> shutdown SQL> exit
3) 이전에 수행된 전체 오프라인 백업 파일로부터 해당 파일을 재설치하고 데이터 파일 완전복구 방법을 이용한 복구작업을 수행하십시오. <xmp style="PADDING-BOTTOM: 10px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; BACKGROUND: #f4f4f4; PADDING-TOP: 10px"></xmp>[C:\] cd c:\backup [C:\] copy users01.dbf c:\oracle\oradata\ora92\users01.dbf [C:\]sqlplus "/as sysdba" SQL> startup Database mounted. ORA-01113: 9 파일이 매체 복구되어야 합니다. ORA-01110: 9 데이터 파일: C:\ORALCE\ORADATA\ORA92\USERS01.DBF SQL> SELECT * FROM V$RECOVER_FILE; FILE# ONLINE ERROR CHANGE# ------ --------- ------------- ----------------- 9 ONLINE 406577 SQL> select FILE#, STATUS, NAME from v$datafile; ← USERS01.DBF 파일은 삭제되었지만 데이터 딕션어리에는 해당 파일이 아직 사용 가능한 상태로 나타납니다.(ONLINE 컬럼이 ONLINE) 데이터 파일 완전복구 작업을 수행하기 위해서는 OFFLINE 상태이어야 합니다. SQL> alter database datafile 'c:\oracle\oradata\ora92\users01.dbf' offline; SQL> alter database open; ← 컨트롤 파일 내에 USERS01.DBF 파일의 상태가 OFFLINE 되었기 때문에 오라클 서 버를 오픈할 수 있습니다. 이 의미는 USERS01.DBF가 ONLINE 상태에서는 항상 파 일의 존재 유무를 확인하게 되지만, OFFLINE 상태에서는 확인하지 않기 때문에 오라클 서버를 오픈할 수 있게 됩니다. SQL> recover datafile ' c:\oracle\oradata\ora92\users01.dbf' ; ORA-00279: Change 7220 generated at 02/24/97 23:51:30 needed ORA-00289: Suggestion : c:\oracle\oradata\ora92\arch\arch_219.arc ORA-00280: Change 7220 for thread 1 is in sequence #219 Specify log: {<ret>=suggested | filename | AUTO | CANCEL} Auto ← 관련된 모든 아카이브 파일들을 자동으로 적용해 줍니다. Media Complete Recovery … ← 정상적으로 복구작업이 완료되었습니다. SQL> select count(*) from scott.dept; - → USERS01.DBF 파일은 아직 OFFLINE 상태이기 때문에 검색할 수 없습니다. SQL> alter database datafile 'c:\oracle\oradata\ora92\users01.dbf ' online; SQL> select count(*) from scott.dept; → 정상적으로 수행 됨</ret>

 

Posted by redkite
, |
백업방법
오라클 DB 백업은 1)물리적 백업(physical backup)과, 2)논리적 백업(Logical backup)의 두가지 방법이 있다.

물리적 백업

물리적인 백업은 데이터베이스 파일(데이터 파일, 컨트롤 파일)을 백업하는 것을 뜻하며, DB가 아카이브 모드에서 수행중인 경우에는 아카이브 리두 로그 파일이 자동적으로 생성되므로 데이터 파일, 컨트롤 파일, 아카이브 리두 로그 파일이 백업된다. 
물리적 백업은 다음과 같이 두 가지가 가능하다.

 • 오프라인 백업
 • 온라인 백업

오프라인 백업
Off-line backup은 테이블스페이스나 데이터 파일이 오프라인일 때 실행되는 백업으로, 가장 수행하기 쉬운 백업방법중의 하나이다. 오프라인 백업은 DB를 종료하고, Db와 관련된 모든 물리적인 파일(데이터 파일, 컨트롤 파일, 매개변수 파일)을 운영체제 명령어를 이용하여 복사한다.

이 백업은 데이터 파일의 크기가 매우 큰 경우, 많은 시간이 소요될 수 도 있다. 그래서 오프라인 백업을 whole-backup 또는 cold-backup이라 한다.

$ sqlplus system/manager as sysdba   ☜ DBA로 접속

SQL> select name from v$controlfile;   ☜ 컨트롤 파일의 위치를 확인
 
NAME
--------------------------------------------------------------------------------
/export/home/oracle/app/oracle/oradata/orcl/control01.ctl
/export/home/oracle/app/oracle/oradata/orcl/control02.ctl
/export/home/oracle/app/oracle/oradata/orcl/control03.ctl
 
SQL> select file_name from dba_data_files;   ☜ 데이터 파일의 확인
 
FILE_NAME
--------------------------------------------------------------------------------
/export/home/oracle/app/oracle/oradata/orcl/users01.dbf
/export/home/oracle/app/oracle/oradata/orcl/sysaux01.dbf
/export/home/oracle/app/oracle/oradata/orcl/undotbs01.dbf
/export/home/oracle/app/oracle/oradata/orcl/system01.dbf
 
SQL> select group#,member from v$logfile;   ☜ 리두 로그 파일을 확인
 
    GROUP# MEMBER
---------- ------------------------------------------------------------
         3 /export/home/oracle/app/oracle/oradata/orcl/redo03.log
         2 /export/home/oracle/app/oracle/oradata/orcl/redo02.log
         1 /export/home/oracle/app/oracle/oradata/orcl/redo01.log
 
SQL>
SQL> shutdown normal;    ☜ normal, transaction, immediate중 하나로 DB를 종료
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> !    ☜ 쉘 프롬프트로 일시 복귀함
$ su     ☜ root의 권한을 가짐
Password: 
# cp /export/home/oracle/app/oracle/oradata/orcl/control0*.ctl /export/home/work/.     ☜ 컨트롤 파일 복사
# cp /export/home/oracle/app/oracle/oradata/orcl/redo*.log /export/home/work/.    ☜ 리두 로그 파일 복사
# cp /export/home/oracle/app/oracle/oradata/orcl/*.dbf /export/home/work/.     ☜ 데이터 파일 복사
# cp dbs/*.ora /export/home/work/.    ☜ 파라미터 파일 복사
# ls -l /export/home/work     ☜ 복사되었나 확인
-rw-r-----   1 root     other      2867200 Jan  4 11:07 control01.ctl
-rw-r-----   1 root     other      2867200 Jan  4 11:07 control02.ctl
-rw-r-----   1 root     other      2867200 Jan  4 11:07 control03.ctl
-rw-r--r--   1 root     other         8384 Jan  4 11:14 init.ora
-rw-r--r--   1 root     other        12920 Jan  4 11:14 initdw.ora
-rw-r-----   1 root     other     10486272 Jan  4 11:09 redo01.log
-rw-r-----   1 root     other     10486272 Jan  4 11:09 redo02.log
-rw-r-----   1 root     other     10486272 Jan  4 11:09 redo03.log
-rw-r-----   1 root     other         2560 Jan  4 11:14 spfileorcl.ora
-rw-r-----   1 root     other    461381632 Jan  4 11:10 sysaux01.dbf
-rw-r-----   1 root     other    471867392 Jan  4 11:11 system01.dbf
-rw-r-----   1 root     other     20979712 Jan  4 11:11 temp01.dbf
-rw-r-----   1 root     other     26222592 Jan  4 11:11 undotbs01.dbf
-rw-r-----   1 root     other      5251072 Jan  4 11:11 users01.dbf

# exit     ☜ root 권한에서 빠져나옴
$ exit       ☜ 쉘프롬프트에서 오라클 프롬프트로 복귀
 
SQL> startup   ☜ Instance 기동
ORACLE instance started.
 
Total System Global Area  289406976 bytes
Fixed Size                   778796 bytes
Variable Size              99360212 bytes
Database Buffers          188743680 bytes
Redo Buffers                 524288 bytes
Database mounted.
Database opened.
SQL> 

자동으로 오프라인 백업실행하기
오프라인 백업은 데이터 파일의 크기가 작은 경우 쉽고, 간단하게 실행할 수 있지만, 데이터 파일이 큰 경우는 많은 시간이 소요되므로 스크립트를 사용하여 운영체제의 스케듈러에 의해 백업이 자동으로 실행되도록 할 수 있다.
다음과 같이 오프라인 자동 백업 스크립트를 작성하여 실행한다.

1단계 : 오라클 인스턴스 종료
 $ORACLE_HOME/bin/sqlplus system/manager as sysdba
 SHUTDOWN IMMEDIATE
 EXIT

2단계 : 데이터베이스와 관련된 모든 물리적 파일 복사
 cp /export/home/oracle/app/oracle/oradata/orcl/*.ctl backup/
 cp /export/home/oracle/app/oracle/oradata/orcl/*.dbf backup/
 cp /export/home/oracle/app/oracle/oradata/orcl/*.log backup/
 cp /export/home/oracle/app/oracle/oradata/orcl/*.ora backup/

3단계 : 데이터베이스 다시 시작
 $ORACLE_HOME/bin/sqlplus system/manager as sysdba
 STARTUP
  EXIT
 EOF

온라인 백업
오프라인 백업이 DB가 종료한 상태에서 백업하는 것에 반해, 온라인 백업은 DB를 운영하는 도중에 백업을 실행하는 방법이다. 온라인 백업은 테이블스페이스 단위로 백업을 수행하며 ALTER TABLESPACE 명령으로 테이블스페이스를 백업모드로 설정하고, 데이터 파일을 운영체제에 복사한다.
온라인 백업을 hot backup 또는 open backup이라 한다. 온라인 백업은 오프라인 백업과 달리 모든 파일을 백업할 수 없고, 필요한 테이블스페이스만 백업할 수 있다.
$ sqlplus '/as sysdba'
SQL> select tablespace_name, file_name from dba_data_files;
 
TABLESPACE_NAME FILE_NAME
--------------- ------------------------------------------------------------
USERS           /export/home/oracle/app/oracle/oradata/orcl/users01.dbf
SYSAUX          /export/home/oracle/app/oracle/oradata/orcl/sysaux01.dbf
UNDOTBS1        /export/home/oracle/app/oracle/oradata/orcl/undotbs01.dbf
SYSTEM          /export/home/oracle/app/oracle/oradata/orcl/system01.dbf
 
SQL> alter tablespace users begin backup; 
☜ 테이블스페이스내의 모든 객체에 대해 변경된 데이터들이 데이터 파일에 적용되고, 메모리 영역과 리두 로그 파일에 일시적으로 저장된다.
 
Tablespace altered.
 
SQL> !
$ cp /export/home/oracle/app/oracle/oradata/orcl/users01.dbf bkup/.
$ ls -l bkup
total 10272
-rw-r-----   1 oracle   oinstall 5251072 Jan  4 14:07 users01.dbf
$ exit
 
SQL> alter tablespace users end backup;  
☜ 복사후 sql문을 실행하여 데이터파일에 저장되었던 변경된 데이터를 실제 데이터 파일에 반영한다.
 
Tablespace altered.
 
SQL> 
SQL> ALTER SYSTEM SWITCH LOGFILE;
    ☜ 인위적으로 로그 스위치를 실행하여 모든 데이터 파일 헤더에 저장되어 있는 체크포인트 번호를 통합
 
System altered.
 
SQL>

논리적 백업

논리적 백업은 DB내의 논리적 객체들을 백업하는 방법으로, EXPORT 유틸리티를 사용하여 백업하고, IMPORT 유틸리티를 사용하여 복구한다.
EXPORT와 IMPORT 유틸리티가 백업/복구 이외에 다른 기능은 다음과 같다.

• 특정 사용자의 객체를 다른 사용자의 공간으로 이동시킬 수 있다.
• 운영체제가 다른 DB 사이에 데이터를 이동시킬 수 있다.
• 테이블, 뷰,인덱스 등을 백업하고 다시 복구함으로써 객체들의 구조가 재생성되어
   단편화(fragmentation)를 감소시킨다.
익스포트에서 사용 가능한 키워드는 EXP 유틸리티를 참조하고
또한 익스포트를 사용하여 논리적으로 DB를 백업하는 방법은 데이터 베이스 전체모드, 테이블스페이스 모드, 사용자모드, 테이블모드의 4 종류가 있다.

데이터베이스 전체모드 테이블스페이스 모드 사용자 모드 테이블 모드
•모든 테이블의 데이터
•인덱스
•테이블의 제약조건
•트리거
•클러스트
•시퀀스
•스냅샷
•스토어드 프로시저
•시노늄
•뷰
•프로파일/롤
•audit
•지정된 테이블스페이스의 테이블
•테이블의 데이터
•인덱스
•테이블의 제약조건
•트리거
•클러스트
•시퀀스
•스냅샷
•스토어드 프로시저
•시노늄
•뷰
•프로파일/롤
•audit
•정의된 사용자의 테이블
•테이블의 데이터
•사용자의 권한
•사용자의 인덱스
•테이블의 제약조건
•테이블의 트리거
•클러스트
•데이터베이스 링크
•스냅샷
•스토어드 프로시저
•시노늄
•뷰
•정의된 사용자의 테이블
•테이블의 데이터
•사용자의 권한
•사용자의 인덱스
•테이블의 제약조건
•트리거


전체백업과 부분백업


전체백업
모든 데이터 파일과 컨트롤 파일을 백업하는 방식으로, 가장 보편적인 방법이다. 전체 백업은 데이터베이스 모드에 관계없이 가능하지만, 아카이브 모드인 경우와 노아카이브 모드인 경우 전체 백업을 수행했을 때의 차이가 있다.
데이터베이스 전체에 대한 백업은 다음과 같은 방법으로 가능하다.
 • 컨트롤 파일 뿐만 아니라 모든 데이터 파일을 복사하는 운영체제가 제공하는 유틸리티
        • RMAN BACKUP DATABASE 명령어
        • 데이터베이스 내의 각 데이터 파일에 대해 수행되는 RMAN COPY DATAFILE 명령어와
  컨트롤 파일에 대해 실행되는 COPY CURRENT CONTROLFILE 명령어

부분백업
전체 데이터베이스를 백업하는 대신 테이블스페이스나 컨트롤 파일과 같이 일부분만을 백업하는 방법이다. 부분 백업은 아카이브 모드에서만 가능하므로, 현재 DB가 아카이브 모드인지 확인해야 한다. 부분 백업에는 테이블스페이스 백업, 데이터 파일 백업, 컨트롤 파일 백업, 아카이브 리두 로그 파일 백업이 있다.
데이터 파일의 백업 상태는 v$backup 뷰로 확인이 가능하다.
 SQL> select log_mode from v$database; ☜ 현제 DB의 아카이브 모드 확인
 SQL> alter database archivelog;  ☜ DB의 모드를 아카이브모드로 전환

테이블스페이스 백업/ 데이터 파일 백업

1) 온라인 테이블스페이스 백업하기
테이블스페이스 백업은 테이블스페이스를 구성하는 데이터 파일을 백업하는 것으로, DB가 아카이브모드라면, 온라인 또는 오프라인 상태에서도 가능하다.

SQL> select tablespace_name, file_name from dba_data_files;
 
TABLESPACE_NAME FILE_NAME
--------------- ------------------------------------------------------------
USERS           /export/home/oracle/app/oracle/oradata/orcl/users01.dbf
SYSAUX          /export/home/oracle/app/oracle/oradata/orcl/sysaux01.dbf
UNDOTBS1        /export/home/oracle/app/oracle/oradata/orcl/undotbs01.dbf
SYSTEM          /export/home/oracle/app/oracle/oradata/orcl/system01.dbf
 
SQL> alter tablespace users begin backup; ☜ users 테이블스페이스에 대해 백업 시작을 알림
 
Tablespace altered.
 
SQL> ! 
$ cp /export/home/oracle/app/oracle/oradata/orcl/users01.dbf bkup/.
$ exit
 
SQL> alter tablespace users end backup;  ☜ users 테이블스페이스에 대해 백업 종료를 알림
 
Tablespace altered.
 
SQL> select * from v$backup;
 
     FILE# STATUS                CHANGE# TIME
---------- ------------------ ---------- ------------
         1 NOT ACTIVE                  0
         2 NOT ACTIVE                  0
         3 NOT ACTIVE                  0
         4 NOT ACTIVE            2858563 04-JAN-06
 
SQL>
2) 오프라인 테이블스페이스 백업하기
사용중인 테이블스페이스를 오프라인시켜 백업할 수 있다. 그러나 SYSTEM 테이블스페이스와 현재 사용중인 롤백 세그먼트는 오프라인 시킬 수 없다는 것을 의미한다.
SQL> select tablespace_name, file_name from dba_data_files;
 
TABLESPACE_NAME FILE_NAME
--------------- ------------------------------------------------------------
USERS           /export/home/oracle/app/oracle/oradata/orcl/users01.dbf
SYSAUX          /export/home/oracle/app/oracle/oradata/orcl/sysaux01.dbf
UNDOTBS1        /export/home/oracle/app/oracle/oradata/orcl/undotbs01.dbf
SYSTEM          /export/home/oracle/app/oracle/oradata/orcl/system01.dbf
 
SQL> alter tablespace users offline normal;
 
Tablespace altered.
 
SQL> !
$ cp /export/home/oracle/app/oracle/oradata/orcl/users01.dbf bkup/.
$ exit
 
SQL> alter tablespace users online;
 
Tablespace altered.
 
SQL>

컨트롤 파일 백업
오라클 DB를 설치하면 CREATE DATABASE 문에 의해 기본적으로 생성되는 파일들이 있는데, 리두 로그 파일, SYSTEM 데이터 파일, UNDO 데이터 파일, TEMP 데이터 파일등의 경로와 파일명을 설정한다. 정상적으로 실행되면 컨트롤 파일이 생성된다
자동으로 생성된는 컨트롤 파일에는 CREATE DATABASE 문에 의해 정의된 파일의 모든 정보가 기록된다. DB가 MOUNT 단계가 되면 컨트롤 파일의 정보를 읽어 DB의 모든 상태를 점검한다. 이때 컨트롤 파일을 읽을 수 없으면 DB를 사용할 수 없다. 따라서 컨트롤 파일을 잘 관리해야 한다. DB를 설치하면 기본적으로 3개의 컨트롤 파일이 생성되는데 첫 번째 파일이 원본 컨트롤 파일고, 나머지 두 개의 파일은 원본에 대한 미러링(mirroring) 파일로 원본 컨트롤 파일에 문제가 발생하면 미러링 파일로 복구할 수 있다.
현재 DB에서 사용하고 있는 컨트롤 파일의 위치와 이름은 v$controlfile 뷰를 참조하여 확인할 수 있다.
SQL> select * from v$controlfile;
 
STATUS  NAME                                                         IS_
------- ------------------------------------------------------------ ---
        /export/home/oracle/app/oracle/oradata/orcl/control01.ctl    NO
        /export/home/oracle/app/oracle/oradata/orcl/control02.ctl    NO
        /export/home/oracle/app/oracle/oradata/orcl/control03.ctl    NO
 
SQL> 
컨트롤 파일을 백업하는 세가지 방법
방법1) 컨트롤 파일 백업
SQL> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> !
$ cp /export/home/oracle/app/oracle/oradata/orcl/*.ctl bkup/.
$
$ ls dbs/*.ora
dbs/init.ora        dbs/initdw.ora      dbs/spfileorcl.ora
initDB명.ore 파일에 복사된 컨트롤 파일을 추가 한다.
 ...
 CONTROL_FILES=(control01.ctl,..,control04.ctl)
 ...
$ exit
 
SQL> startup
ORACLE instance started.
 
Total System Global Area  289406976 bytes
Fixed Size                   778796 bytes
Variable Size              99360212 bytes
Database Buffers          188743680 bytes
Redo Buffers                 524288 bytes
Database mounted.
Database opened.
SQL>
방법2) spfile을 사용한 컨트롤 파일 백업
SQL> ALTER SYSTEM SET control_files=
   '/export/home/oracle/app/oracle/oradata/orcl/control01.ctl',
   '/export/home/oracle/app/oracle/oradata/orcl/control02.ctl',
   '/export/home/oracle/app/oracle/oradata/orcl/control03.ctl', SCOPE=SPFILE;
SQL> SHUTDOWN
SQL> !
# cp control01.ctl control04.ctl
# exit
SQL> STARTUP
방법3) ALTER DATABASE 명령을 사용한 방법

 ALTER DATABASE BACKUP CONTROLFILE TO TRACE;
alter database 명령을 실행하여 컨트롤 파일을 백업하면 생성된 복사본은 바이너리 파일로 생성되는 대신 텍스트 형식으로 백업 파일을 저장한다. 만일 원본 컨트롤 파일과 복사본 컨트롤 파일 모두를 사용할 수 없다면, 이 파일을 사용하여 모든 컨트롤 파일을 재생성할 수 있다.
백업된 파일은 initDB명.ora 파일의 user_dump_dest 매개변수가 지정하는 경로에 *.trc 확장자로 생성된다. 
이렇게 백업된 *.trc 콘트럴 파일로부터 컨트롤 파일을 다시 복구하는 방법은 이곳에 있음 
다음과 같은 경우 alter database 명령문을 실행하여 컨트롤 파일에 대한 trc 파일을 생성하는 것이 좋다.
• ALTER DATABASE 명령어에 의해 db의 구조가 변경될 때
• CREATE TABLESACE 명령어에 의해 테이블스페이스가 추가 되거나 변경될 때
• DROP TABLESPACE 명령어를 사용하여 테이블스페이스가 삭제될 때
SQL> alter database backup controlfile to trace;
 
Database altered.
 
SQL> show parameter user_dump_dest;
 
NAME              TYPE        VALUE
----------------- ----------- ------------------------------------------------
user_dump_dest    string      /export/home/oracle/app/oracle/admin/orcl/udump
SQL>

 

Posted by redkite
, |

*. REDO LOG group은 3개 이상 권장, member는 2개 권장

   (member는 물리적으로 서로 다른 위치에 분산 권장)
*. 평상시 REDO LOG 스위치가 약 20분 이상 유지할 수 있는 Size 권장
   (alert_TESTDB.log에서 지속적으로 모니터링해서 필요시 REDO LOG 크기를 증가시킬 것)

*. 체크포인트 간격 조절(initTESTDB.ora파라미터에서) fast_start_mttr_target = 600

*. DB Startup 상태에서 작업 가능


1. sqlplus 접속(Internal로 접속)
   $> sqlplus '/ as sysdba'
   OR
   $> sqlplus system/manager

 

2. currunt REDO LOG 조회

   SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
         1          1         43  104857600          2 YES INACTIVE               8485439 01-SEP-03
         2          1         44  104857600          2 YES INACTIVE               8585874 02-SEP-03
         3          1         45  104857600          2 NO  CURRENT                8756665 03-SEP-03

   STATUS가 Inactive인 경우만 작업 가능

 

3. REDO LOG file을 switch
   SQL> alter system switch logfile;
   SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
         1          1         46  104857600          2 NO  CURRENT                8988801 03-SEP-03
         2          1         44  104857600          2 YES INACTIVE               8585874 02-SEP-03
         3          1         45  104857600          2 YES ACTIVE                 8756665 03-SEP-03

   SQL> alter system switch logfile;
   SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
         1          1         46  104857600          2 YES ACTIVE                 8988801 03-SEP-03
         2          1         47  104857600          2 NO  CURRENT                8990631 03-SEP-03
         3          1         45  104857600          2 YES INACTIVE               8756665 03-SEP-03

 

4. acitive 한 REDO LOG group을 inactive로 변경
   SQL> alter system checkpoint;

 

5. REDO LOG Drop
   SQL> alter database drop logfile group 2;

6. REDO LOG logfile 삭제
   SQL> !rm /oradata1/redo2a.dbf;
   SQL> !rm /oradata2/redo2b.dbf;

 

7. REDO LOG logfile 추가
   1) 멤버가 없는 경우
      SQL> alter database add logfile group 2 '/oradata/redo2.dbf' size 100M;

   2) 멤버가 있는 경우
      SQL> alter database add logfile member  '/oradata/redo2b.dbf' to group 2;

      SQL> alter database add logfile
                 group 2 ('/oradata1/redo2a','/oradata2/redo2b') size 100M reuse;
   3) 여러개의 REDO LOG 추가할 경우
      SQL> alter database add logfile
                 group 4 ('/oradata1/redo4a','/oradata2/redo4b') size 100M,
                 group 5 ('/oradata1/redo5a','/oradata2/redo5b') size 100M,
                 group 6 ('/oradata1/redo6a','/oradata2/redo6b') size 100M;

 

Posted by redkite
, |

오라클9i 이상 filesystem UNDO TABLESPACE 변경
- All undo tablespaces are created permanent, read/write, and in logging mode.

 

1. 기존 UNDO TABLESPACE를 DROP 후 CREATE

    SQL> connect / as sysdba

    SQL> CREATE  UNDO TABLESPACE UNDOIMSI

                           DATAFILE '/oradata/undoimsi.dbf' SIZE 10M;
    SQL> ALTER SYSTEM SET UNDO_TABLESPACE=UNDOIMSI;

    SQL> DROP TABLESPACE UNDOTBS1 INCLUDING CONTENTS AND DATAFILES;
    SQL> CREATE  UNDO TABLESPACE "UNDOTBS1"
                           DATAFILE '/oradata/undotbs01.dbf' SIZE 500M
                           EXTENT MANAGEMENT LOCAL;
   SQL> ALTER SYSTEM SET UNDO_TABLESPACE=UNDOTBS1;

   SQL> DROP TABLESPACE UNDOIMSI INCLUDING CONTENTS AND DATAFILES;

 

2. UNDO datafile Resize
    SQL> connect / as sysdba

    SQL> alter database datafile '/oradata/UNDOTBS01.dbf' resize 4000M;

 

Posted by redkite
, |

테이블스페이스(TABLESPACE)

-------------------------
 - 오라클 서버가 데이터를 저장하는 논리적인 구조
 - 테이블스페이스는 1개 또는 여러 개의 데이터파일을 가진 논리적인 데이터 저장 구조

 - LMT(Locally Managed Tablespace)

 - DMT(Dictionary Managed Tablespace)

 - Next Extent크기는 64KB, 1MB, 8MB, 64MB 순으로 사용됨
 - AUTOALLOCATE의 경우

   처음 테이블의 EXTENT는 64KB부터 시작, 1MB가 될 때까지 64KB단위로 증가,

   1MB가 된 이후부터는 1MB단위로 증가, 이후부터는 64MB가 되었을 때 8MB,
   1GB가 되었을 때 64MB단위로 증가


--------------------------------------------

테이블스페이스 생성

--------------------------------------

 

1. 데이터파일 raw device인 경우(9i~)


    SQL> CREATE TABLESPACE       테이블스페이스명
         datafile  '/dev/vg_data01/rlvol_test' [size  99M]
         EXTENT MANAGEMENT LOCAL     -- Default is LOCAL

                                     -- (LOCAL/DICTIONARY Managed Tablespace)
         [AUTOALLOCATE] or [UNIFORM SIZE 1M]  -- Auto Extent Size or Uniform Extent Size

                                              -- (initial이 지정되었을 경우 initial Size)
         SEGMENT SPACE MANAGEMENT AUTO        -- freelist 및 pctused 등을 자동으로 관리

         ;                                    -- (AUTO/MANUAL)

 

2. 데이터파일 file system인 경우
    SQL> CREATE TABLESPACE 테이블스페이스명
         datafile   '/data01/데이터파일명'  size  100M
         AUTOEXTEND ON  NEXT 10M

         MAXSIZE 4000M MINIMUM EXTENT 1M -- datafile에 대한 option 임
         EXTENT MANAGEMENT LOCAL         -- Default is LOCAL (LOCAL or DICTIONARY)
         [AUTOALLOCATE] or [UNIFORM SIZE 1M] -- Auto Extent Size or Uniform Extent Size

                                             -- (initial이 지정되었을 경우 initial Size)
         SEGMENT SPACE MANAGEMENT AUTO       -- freelist 및 pctused 등을 자동으로 관리

                                             -- (AUTO/MANUAL)

 

--------------------------------------------

테이블스페이스 관리

--------------------------------------

 

1. COALESCE

    SQL> alter tablespace 테이블스페이스명 coalesce ;

         - ORACLE 7, 8, 8i, 9i DICTIONARY Management Tablespace일 경우 사용

           (Locally Managed Tablespace는 coalesce가 필요 없음)
         - For each datafile in the tablespace,
           this clause coalesces all contiguous free extents

           into larger contiguous extents. 

 

2. RENAME

    SQL> ALTER TABLESPACE 구테이블스페이스명 RENAME TO 신규테이블스페이스명;

         - 9i이하에서는 지원하지 않음, 10g부터 지원
         - 사용자의 DEFAULT TABLESPACE 함께 변경됨
           SQL> SELECT * FROM DBA_USERS;
           SQL> ALTER USER 사용자명 DEFAULT TABLESPACE 테이블스페이스명;

 

3. Read/Write

    SQL> alter tablespace 테이블스페이스명 read only ;

         - read only 테이블스페이스는 온라인(HOT) 백업에서 제외됨

   SQL> alter tablespace 테이블스페이스명 read write ;

 

4. Online/Offline

   SQL> alter tablespace 테이블스페이스명 online;

   SQL> alter tablespace 테이블스페이스명 offline;

 

5. Drop

   SQL> drop tablespace 테이블스페이스명;

   SQL> drop tablespace 테이블스페이스명 including contents cascade;

   SQL> drop tablespace 테이블스페이스명 including contents cascade constraints;
   SQL> DROP TABLESPACE TBS1 INCLUDING CONTENTS AND DATAFILES;

        - (9i~) 데이타파일도 함께 삭제

 

6. LMT to DMT/DMT to LMT

   - 8.1.5는 LMT에서 DMT로 변환만이 가능
   - 8.1.6 이상부터 LMT와 DMT 상호변환 가능
   - 테이블스페이스의 Segment Management가 Auto로 되어 있거나 Compress되어 있으면
     테이블스페이스 마이그레이션이 되지 않음
   SQL> EXECUTE DBMS_SPACE_ADMIN.TABLESPACE_MIGRATE_FROM_LOCAL('테이블스페이스명');

   SQL> EXEC DBMS_SPACE_ADMIN.TABLESPACE_MIGRATE_TO_LOCAL('테이블스페이스명');

 

7. 온라인(HOT) 백업

   SQL> ALTER TABLESPACE 테이블스페이스명 BEGIN BACKUP;
        테이블스페이스에 속하는 데이터파일들 cp 명령어 또는 dd 명령어로 복사
   SQL> ALTER TABLESPACE 테이블스페이스명 END   BACKUP;

 

8. 데이터파일이 손상되었을 때 데이터파일 offline drop 후 복구
   SQL> alter database datafile '/data01/데이터파일명' offline drop;

   - 해당 테이블스페이스 온라인 백업 불가

 

9. 데이터파일에 사용하는 세그먼트가 없을 경우 해당 데이터파일 DROP 가능
   SQL> alter tablespace drop datafile '/data01/데이터파일명';

 

10. 사용량/사용율 조회

    SQL> SELECT A.TABLESPACE_NAME,
                SUM(A.BYTES)/1024                                       AS "TOTAL(KB)",
                SUM(A.BYTES)/1024 - NVL(SUM(SZ_KB),0)                   AS "USED(KB)",
                NVL(SUM(SZ_KB),0)                                       AS "FREE(KB)",
                NVL(( 1. - SUM(SZ_KB)/(SUM(A.BYTES)/1024.) ) * 100,100) AS "USED RATIO(%)"
           FROM DBA_DATA_FILES A,
                ( SELECT FILE_ID  ,
                         SUM(BYTES)/1024. AS SZ_KB
                    FROM DBA_FREE_SPACE
                   GROUP BY FILE_ID
                ) B
          WHERE A.FILE_ID = B.FILE_ID(+)
          GROUP BY A.TABLESPACE_NAME;

 

Posted by redkite
, |
DECODE()함수의 Return 값
 
Return값 = DECODE(expr, search, result [, search, result ]...  [, default ])
<pre> </pre>
- DECODE() 함수의 Return값첫번째 result(3번째 인수)의 Datatype에 따라 달라진다.
- 첫번째 result(3번째 인수)가 null 이라면 Return값의 Datatype은 String이다.
- 첫번째 result(3번째 인수)와 나머지 result나 defaut의 Datatype이 다르면
  "ORA-01722: 수치가 부적합합니다." 에러가 발생한다.

 

------------------------------------------------------------------------------------------

Oracle® Database SQL Reference
10g Release 2 (10.2)
Part Number B14200-02

 

[Purpose]

DECODE compares expr to each search value one by one.

If expr is equal to a search, then Oracle Database returns the corresponding result.

If no match is found, then Oracle returns default.

If default is omitted, then Oracle returns null.

 

The arguments can be any of the numeric types (NUMBER, BINARY_FLOAT, or BINARY_DOUBLE)

or character types.

- If expr and search are character data,

then Oracle compares them using nonpadded comparison semantics.

expr, search, and result can be any of the datatypes CHAR, VARCHAR2, NCHAR, or NVARCHAR2.

The string returned is of VARCHAR2 datatype and is in the same character set

as the first result parameter.

- If the first search-result pair are numeric,

then Oracle compares all search-result expressions and the first expr to determine

the argument with the highest numeric precedence, implicitly converts the remaining

arguments to that datatype, and returns that datatype.

 

The search, result, and default values can be derived from expressions.

Oracle Database uses short-circuit evaluation.

That is, the database evaluates each search value only before comparing it to expr,

rather than evaluating all search values before comparing any of them with expr.

Consequently, Oracle never evaluates a search if a previous search is equal to expr.

Oracle automatically converts expr and each search value to the datatype

of the first search value before comparing.

 

Oracle automatically converts the return value to the same datatype as the first result.

If the first result has the datatype CHAR or if the first result is null,

then Oracle converts the return value to the datatype VARCHAR2.

 

In a DECODE function, Oracle considers two nulls to be equivalent.

If expr is null, then Oracle returns the result of the first search that is also null.

 

The maximum number of components in the DECODE function, including expr,

searches, results, and default, is 255.

Posted by redkite
, |
  • Primary Key 컬럼 순서와 데이터베이스 성능

프린트 이메일 전송

데이터 처리를 할 때 Primary Key(PK)의 역할은 거의 절대적이라 할 수 있다. 웬만한 트랜잭션 처리는 모두 PK를 이용해 처리하기 때문이다. 만일 우리가 설계하는 데이터 모델에서 PK를 이용하는 부분에 비효율적인 면이 있다면 어떻게 될까? 그것이 주는 영향은 단순히 SQL 몇 개를 튜닝하는 정도가 아니라, 해당 테이블을 이용하는 전 트랜잭션에 영향을 주는 치명적인 문제가 될 수 있다.

이춘식 csklee11@chol.com|현재 LG CNS DB관리팀장으로 국내외 데이터베이스를 총괄해 운영하는 리더를 맡고 있다. '데이터베이스 설계와 구축'이라는 전문서로 수많은 프로젝트 설계방법을 제시했으며, 진단을 통한 실질적인 문제점과 개선점을 제시했다. 데이터베이스 영역과 함께 기술사/감리사로서 강의, 집필, 평가위원, 자격 검정위원 등의 활동을 수행하고 있다. 저서로 데이터베이스 설계와 구축, 아는 만큼 보이는 데이터베이스 등 총 9권이 있다.

IT 프로젝트를 진행하면서 테이블을 추가하거나 변경할 때, PK 컬럼 구성과 컬럼 순서를 중요하게 생각하지 않은 채 있는 그대로 테이블을 생성하는 경우가 많이 있다.

실제로 많은 프로젝트를 진단해보면, 설계단계 끝 부분을 트랜잭션이 들어오는 특성을 분석해 적절하게 PK 순서를 조정해야 되지만 그렇지 않고 데이터 모델링이 된 그대로 DDL(Data Definition Language)을 생성해 테이블을 만들어버리는 경우가 비일비재하다. 그렇게 한참을 개발 한 후, 충분한 테스트 데이터를 생성해 실행하면 성능이 좋지 않아 그때 새로운 인덱스를 추가해 결국 오버헤드를 유발하는 경우가 발생한다.

테이블 생성 이전에 SQL Where 절 조건을 분석하라
여러 개의 컬럼으로 구성된 PK 구성 테이블을 있는 그대로 생성할 경우 어떤 일이 발생할까? 먼저 의도하지 않은 인덱스 구성인 'Primary Key Unique Index'가 생성될 것이다. 그에 따라 조회 SQL 실행 시 성능이 저하되거나 설계로 인해 생성된 인덱스 외의 추가 인덱스를 생성하게 돼 결국 인덱스 과다로 입력, 수정, 삭제 등 불필요한 내부 작업이 증가 할 것이다. 결국 불필요한 작업으로 또 다른 성능저하의 원인이 된다.

따라서 테이블 생성 이전에 설계단계에서 엔티티 타입의 PK 컬럼 순서를 SQL Where 절을 분석해 조정하는 작업이 위 문제를 해결하는데 가장 중요한 열쇠가 된다.

데이터베이스는 분석 - 설계 - 구축 - 테스트 - 이행의 IT 프로젝트 진행 라이프 사이클 중 설계단계 이후에 완성된 데이터 모델을 토대로 물리적인 테이블을 정해진 DBMS에 맞게 생성한다. 보통 상용화된 데이터모델링 툴(ERStudio, ERWin, DA# 등)을 이용해 데이터 모델을 만들고 DDL을 생성하기 때문에, 설계단계 말 즉 데이터베이스 생성단계에서 PK 컬럼의 순서를 고려하지 않고 생성하는 경우가 많이 있다.

<그림 1> PK 순서, 반드시 조정해라

PK 순서를 잘못 지정해 성능이 저하된 경우(단순한 오류)
설계단계에서 데이터모델링을 종료하고 스키마 정보를 생성하기 전, 데이터 모델의 PK 순서를 조정하지 않고 테이블을 생성하면 인덱스를 이용하지 못해 테이블을 Full Scan하는 현상이 발생될 수 있다.

학사관리 업무에서 데이터 모델에 따른 PK 구성을 예로 들어보겠다. '입시마스터'라는 테이블의 PK는 수험번호+년도+학기로 구성돼 있고, '전형과목 실적' 테이블은 입시마스터 테이블에서 상속받은 수험번호+년도+학기에 전형과목 코드로 PK가 구성돼 있는 복합 식별자 구조의 테이블이다.

입시마스터에는 200만 건의 데이터가 있으며 학사는 4학기로 구성돼 있다. 데이터의 보관은 5년이다. 한 학기당 평균 1만 건의 데이터가 있다고 가정해보겠다. PK가 수험번호+년도+학기로 구성돼 있으므로 대부분의 자동 DDL 생성 툴은 세 개의 컬럼을 순서 그대로 조합한 인덱스를 생성한다. 이때 입시 마스터의 인덱스를 '입시마스터_I01'이라 하자.

이 테이블 구조에서 <그림 2>와 같은 SQL구문이 실행되면, 입시마스터 테이블에 있는 인덱스 입시마스터_I01을 이용할 수 있을까?

<그림 2> PK 순서에 따라 생성된 인덱스와 SQL - 개선 전

입시마스터_I01 인덱스가 수험번호+년도+학기 중 수험번호에 대한 값이 WHERE 절에 들어오지 않으므로, FULL TABLE SCAN이 발생해 200만 건의 데이터를 모두 읽어 당연히 성능이 저하됐다. 다수의 IT 프로젝트 현장 DB 담당자가 PK컬럼 순서를 조정하지 않아, 인덱스를 이용해야 하는 SQL 문장이 결국 인덱스를 이용하지 못해 성능저하가 발생하는 것이다.

이런 테이블 구성을 효율적으로 개선하기 위해서 인덱스의 정렬구조를 고려하고, 해당 테이블에 들어오는 조회조건을 사전에 분석시켰다. 그래서 설계된 화면정의서의 조회조건을 분석하고, 설계된 SQL 문장의 Where절에 '='이나 'Between', '<', '>' 등을 분석해 PK 컬럼 순서를 범위가 들어오는 조건부터 앞쪽으로 위치시켰다. 즉, 입시마스터 엔티티 타입의 PK 순서를 SQL Where 절에서 조회하는 조건으로 조정했다.

<그림 3> PK 순서에 따라 생성된 인덱스와 SQL - 개선 후

입시마스터 테이블의 데이터를 조회할 때, 년도와 학기에 대한 내용이 빈번하게 들어오므로 이를 이용해 PK순서를 변경, 인덱스를 이용 가능하게 만들었다.

생성된 인덱스가 정상적으로 이용돼 평균 2만 건의 데이터를 처리할 수 있게 돼 성능이 한층 개선됐다. 단순하게 PK 순서만 조정했을 뿐인데 SQL 문장 실행에서 Full Table Scan을 했는지 아니면 Index Scan을 했는지 결정된 것이다. 좀 더 복잡한 다른 예를 보자.

PK 순서를 잘못 지정해 성능이 저하된 경우(복잡한 오류)
A씨는 은행권의 프로젝트를 진행하면서 현금 출급기의 PK 컬럼에 대해 유일성과 최소성 확보를 데이터모델링에선 고려했으나 PK 컬럼 순서에는 신경쓰지 않고 바로 테이블을 생성했다.

이렇게 생성된 현금출급기 실적 테이블의 PK는 거래일자+사무소코드+출급기 번호+명세표번호로 구성돼 있는데, 대부분의 SQL 문장에서는 조회를 할 때 사무소 코드가 '='로 들어오고 거래일자는 'BETWEEN' 조회를 하고 있다. 과연 이러한 유형의 트랜잭션 성능이 좋은 상태로 나타나는 것일까?

<그림 4> PK 순서에 따라 생성된 인덱스와 SQL - 개선 전

A씨가 PK 컬럼을 조정하지 않고 해당 테이블에 업무적인 규칙에 의해 작성된 SQL 구문 이다. 자 그렇다면 인덱스를 이용해볼까? 과연 인덱스를 사용하는 것이 최선의 성능을 가져오는 것일까?

실행계획을 분석하면 인덱스가 정상적으로 이용됐기 때문에 SQL 문장은 잘 튜닝된 것으로 착각할 수 있다. 문제는 인덱스를 이용은 하는데 넓은 Range 조회로 인해 SQL 실행성능이 심각하게 저하된다는 점이다.

<그림 5>는 인덱스를 '거래일자+사무소 코드' 순서로 구성 할 때와 '사무소 코드+거래일자'로 구성할 때 각각 데이터를 처리하는 범위가 어떻게 달라지는지 보여주고 있다.

<그림 5> 인덱스 구성에 따른 데이터 처리범위 변경

거래일자+사무소코드로 구성된 왼쪽은 BETWEEN 비교를 한 거래일자 '20120701'이 인덱스의 앞에 위치하기 때문에 범위가 넓어졌고, 사무소 코드+거래일자로 구성된 오른쪽은 인덱스의 경우 = 비교를 한 사무소 코드 '000368'가 인덱스 앞에 위치해 범위가 좁아졌다. 따라서 인덱스 순서를 고려해 데이터 모델의 PK 순서를 거래일자+사무소 코드+출급기 번호+명세표 번호에서 사무소 코드+거래일자+출급기 번호+명세표 번호로 수정하면 성능을 개선시킬 수 있다.

<그림 5> 구조를 토대로 <그림 6>과 같이 테이블의 PK 구성을 다시 조정해 PK 인덱스 조회 시 범위를 줄여 성능향상을 유도했다.

<그림 6> PK 순서에 따라 생성된 인덱스와 SQL - 개선 후

물론 테이블의 PK 구조를 그대로 둔 상태에서 인덱스만 하나 더 만들어도 성능은 개선될 수 있다. 하지만 이미 만들어진 PK 인덱스가 전혀 사용되지 않는다면 입력, 수정, 삭제 시 불필요한 인덱스로 인한 성능저하를 피할 수 없게 된다. 결국 최적화된 인덱스 생성을 위해는 PK 순서변경을 통한 인덱스 생성이 바람직하다. 테이블을 구축하기 이전에 PK 구성단계에서부터 최적의 성능을 나타낼 수 있도록 PK 순서를 조정하는 작업을 반드시 수행해야 한다.

PK 컬럼 순서구성에 대한 결론
지금까지 강조해 온 PK 컬럼 순서를 통한 성능저하 예방의 핵심은 프로젝트 설계단계의 마지막인 데이터모델링 수행 시 다수의 컬럼을 사용하는 PK 컬럼 순서에 대해 트랜잭션의 패턴을 분석하고, 이를 검토해 조정해야 한다는 것이다.

PK 순서가 잘못돼 SQL 문장의 성능이 저하되는 경우는 크게 두 가지다. 첫 번째는 단순한 오류 사례와 같이 인덱스를 이용하지 못하고 FULL TABLE SCAN 하면서 성능이 저하되는 경우이다. 두 번째는 복잡한 오류 사례와 같이 인덱스는 이용하는데 그 범위가 넓어져 성능이 저하되는 경우다.

보통 첫 번째는 SQL의 실행계획을 보고 쉽게 튜닝을 하는데, 두 번째의 경우는 UNIQUE 인덱스를 이용해야 하지만 성능이 저하되는 이유로 인해 쉽게 튜닝을 못 하는 경우가 빈번하다. 따라서 인덱스의 정렬(SORT) 구조를 이해한 상태에서 트랜잭션의 특성에 따른 PK 구성을 해 인덱스 범위를 최소화 하는 방향을 데이터 모델에 반영해야 한다.

데이터 모델의 PK 순서가 아무 의미 없는 것 같지만 실전 프로젝트에서 의미 없는 PK 순서를 설계해 성능이 저하되는 경우가 아주 빈번하다. 성능저하 현상의 대부분이 PK가 여러 개의 속성으로 구성된 복합 식별자일 때 PK 순서를 고려하지 않고 데이터모델링을 한 경우에서 온다. 이건 단순하지만 자주 범하는 오류다.

이렇게 발생한 설계상의 오류를 해결하기 위해 SQL 구문을 수정하거나 인덱스를 생성하는 방법을 사용하려고 한다. 하지만 이것은 구불구불한 길을 만들어 놓고 그 길을 빨리 가기 위해 또 다른 지름길을 만들거나 구불구불한 길을 빨리 갈 수 있는 차를 임시로 개발하는 것과 같다. 결코 근본적인 해결법이 아니라는 말이다.

특히 물리적인 데이터모델링 단계에서는 스스로 생성된 PK 순서 이외에 다른 엔티티 타입으로부터 상속받아 발생되는 PK 순서까지 항상 주의해 표시해야 한다. PK는 해당 테이블의 데이터에 가장 빈번하게 접근해 사용되는 유일한 인덱스(Unique Index)를 모두 자동으로 생성한다.

PK 순서를 결정하는 기준은 인덱스 정렬구조를 이해한 상태에서 인덱스를 효율적으로 이용할 수 있도록 그 순서를 지정하는 것이다. 즉 인덱스는 그 특성 상 여러 개의 속성이 인덱스 하나로 구성돼 있을 때 앞쪽에 위치한 속성값이 비교자로 있어야 좋은 효율을 나타낸다. 앞쪽에 위치한 속성값이 가급적 '=' 이나 최소한 범위인 'BETWEEN', '< >'에 들어와야 이용할 수 있다. 다시 말하면 그 특성 상 어떤 값이 들어오는지를 예상하고, 데이터베이스에서 발생하는 트랜잭션의 성격을 제대로 이해하지 못하면 원활한 PK 순서를 지정할 수 없게 된다는 것이다. 즉, 데이터모델링에 참여한 사람이 정확한 프로세스의 특징을 이해하지 못한다면 PK 순서를 정확하게 지정할 수 없다는 의미이다.

필자 메모

PK 순서에 대해 자주하는 질문들
Q PK 순서를 고려하지 않아도, 설계 때와는 다른 순서로 인덱스를 만들면 되지 않을까요?

A 대부분의 프로젝트 진단결과, 엔터티 타입의 PK 순서를 그대로 인덱스로 생성하지 별도의 순서로 인덱스를 만드는 경우는 한 군데도 없다. 결국 모든 경우에서 설계된 순서 그대로 인덱스를 생성하는 것이다. 테이블을 생성하는 DBA가 똑똑해서 일부러 설계된 순서와 다르게 PK 인덱스를 생성하면 문제되지 않는다. 하지만 이때도 관리되는 데이터 모델과 데이터베이스의 불일치로 구성관리의 문제라는 또 다른 이슈가 대두될 것이다.

Q 만약 컬럼 순서가 문제된다면 또 하나의 인덱스를 만들면 어떤가요? 예를 들어 A+B 컬럼 순서로 만들었는데 효율이 떨어진다면 B+A로 한 개 더?

A 불필요한 인덱스 한 개는 입력, 수정, 삭제의 효율성을 떨어뜨리는 요인이 된다. 개발은 한 번이지만 시스템이 실제 업무를 지원하기 위해 서비스 되는 기간은 수 십년 동안 지속된다는 점을 기억해야 한다. 불필요한 인덱스로 인해 데이터 처리(입력, 수정, 삭제)의 비용이 지속적으로 많이 소요되는 구조가 될 것이다.

Q 만약 컬럼 순서가 문제가 된다면 기존의 생성된 인덱스는 Drop하고 새롭게 만들면 어떤가요? 예를 들어 A+B 컬럼 순서로 만들었는데 효율이 떨어지면 이것을 Drop하고 B+A로 새로 만들면?

A 실제 프로젝트에서 튜닝은 대부분 실제 데이터를 이관하는 구축 중·후반에 수행된다. 이때 인덱스를 Drop하면 얼마나 많은 SQL 문이 영향을 받을지 장담할 수 없다. 이 말은 Drop을 쉽게 의사결정하지 못한다는 의미다. 더군다나 PK는 테이블 자신 안에서만 사용되는 것이 아니라 다른 테이블로 계속 상속되는 특징을 가지고 있기 때문에 Drop 하려면 연관된 모든 테이블을 고려해야 한다.

따라서 설계단계에서 PK 순서를 조정하고 이후 최적화 작업을 하면서 일부를 조정하는 것이 가장 베스트 솔루션이라 할 수 있다.

Posted by redkite
, |
오라클의 공유 메모리는 커널 작업을 수반하지 않으며 프로세스 간의 데이터 복제 작업이 불필요 하기 때문에 , IPC(inter-Process Communication)를 위한 가장 빠른 방법을 선호 되고 있습니다.
오라클은 인스턴스 구조를 보면 SGA(System Global Area)와 백 그라운드 프로세스로 구성 되어 있습니다. 여기에서 SGA는 Shared Pool, Database Buffer Cache, Redo Log Buffer 등의 저장에 활용되므로 SGA 크기에 따라 오라클 성능이 크게 달라집니다.

그럼 오라클을 설치하기 전에 Linux에서 사용하는 커널 매개변수와 Shell Limit에 대해서 알아 보도록 하겠습니다.


1. Linux 커널 매개변수의 설정

다른 UNIX 시스템과 달리, Linux 운영체제에서는 시스템이 실행 중인 상태에서 대부분의 커널 매개변수를 수정할 수 있습니다. 커널 매개변수를 변경한 뒤에 시스템을 리부팅할 필요도 없습니다. Oracle Database 10g가 요구하는 커널 매개변수 설정할 수 있으나 시스템에 이미 커널 메게변수가 높은 수치로 설정 되어있을 경우에는 변경 하지 마시기 바랍니다.

[ 매개변수 - kernel.shmmax ] SHMMAX 매개변수는 공유 메모리 세그먼트의 최대 크기(바이트 단위)를 정의하는데 사용됩니다. 오라클 SGA 메모리로 구성되며, SHMMAX가 올바르게 설정되지 않을 경우 SGA의 크기가 제약될 수도 있습니다. 따라서 SGA의 크기보다 작지 않도록 SHMMAX를 설정합니다.
총 10GB의 메모리에서 오라클이 사용할 수 있는 최대 한도를 정의 하는 것을 의미 합니다.
먄약 SHMMAX 매개변수가 잘못 설정될 경우에는 아래와 같은 오라클 에러 메시지가 발생 됩니다.

ORA-27123: unable to attach to shared memory segment

기본적으로 SHMMAX 기본 값은 32MB 입니다. SGA로 사용하기에는 너무 적은 공간이기 때문에 적당한 크기로 변경 해야 합니다.
[2010-12-09 03:26:18]-[root@calmmass:/proc/sys/kernel]
# cat /proc/sys/kernel/shmmax |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
33.554.432

[ 매개변수 - kernel.shmall ]
SHMALL 커널 매개변수는 특정 시점에 시스템에서 사용 가능한 공유 메모리의 최대 크기(페이지 단위)를 설정하는데 사용됩니다. 따라서 이 매개변수는 최소한 아래 값보다 커야 합니다.
ceil(SHMAX/PAGE_SIZE)
우선 페이지 사이즈를 확인 해보겠습니다. Red Hat Linux의 페이지 사이즈는 기본적으로 4,096 바이트 입니다.
[2010-12-09 02:51:29]-[root@calmmass:~]
# getconf PAGESIZE |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
4.096

SHMALL의 디폴트 사이즈는 아래와 같습니다. sed를 이용해서 3자리로 구분한 결과 2MB를 사용합니다.
# cat /proc/sys/kernel/shmall |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
2.097.152

[ 매개변수 - kernel.shmmni ] SHMMNI는 공유 메모리 식별자의 개수를 의미 하며 권장 값은 100 이상 으로 설정하셔야 합니다. 아래와 같이 확인 하시기 바랍니다.
[2010-12-09 03:26:07]-[root@calmmass:/proc/sys/kernel]
# cat shmmni
4096

[ 매개변수 - kernel.sem ] 세마포어(Semaphore)란 공유 리소스의 사용 과정에서 프로세스(프로세스 내 쓰레드) 간의 동기화를 위해 사용되는 일종의 카운터(counter) 입니다. 애플리케이션의 세마포어를 이용하면, 운영 체제는 SET를 통해 세마포어를 지원하게 됩니다.
그럼 세마포어 설정 값을 먼저 확인 해보겠습니다.
[2010-12-09 03:39:32]-[root@calmmass:/proc/sys/kernel]
# ipcs -lm
------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 32768
max total shared memory (kbytes) = 8388608
min seg size (bytes) = 1

SEM 매개변수는 세마포어 최대값을 조정 가능하며 의미는 아래와 같습니다.
의미 : {배열당 최대 SEM 수}{최대SEM시스템넓이}{SEMOP호출당최대OP수}{최대배열수}
[2010-12-09 03:37:24]-[root@calmmass:/proc/sys/kernel]
# cat /proc/sys/kernel/sem |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
250 32.000 32 128
1 2 3 4 (필드 라고 정의 하겠습니다.)
1 필드 값(250) : SEMMSL 매개변수는 세미포어 set 당 세마포어의 최대 개수를 정의합니다. 오라클을 예로 init[SID].ora 파일(pfile, spfile 동일)의 PROCESS 인스턴스 매개변수의 (전체 데이터베이스 중) 최대값에 10을 더한 값을 사용할 것을 권장하고 있습니다. 그래서 100이상의 값을 정의하는 것을 권장 합니다.

2 필드 값(32.000) : SEMMNI 매개변수는 전체 Linux 시스템의 세마포어 set의 개수를 정의 합니다. 오라클에서는 100이상의 값을 정의하는 것을 권장합니다.

3 필드 값(32) : SEMMNS 매개변수는 전체 Linux 시스템의 ("세마포어 set"이 아닌) 세마포어의 최대 개수를 정의 합니다. 오라클은 인스턴스 매개변수의 값을 모두 더한 뒤, 가장 큰 Processes값을 두 차례 더하고, 마지막으로 각 데이터베이스 별로 10을 더한 값을 SEMMNS를 설정하도록 권장 합니다.

4. 필드 값(128) : SEMOPM 매개변수는 semop 시스템 호출(system call) 별로 수행될 수 있는 세마포어 작업의 수를 설정하는데 사용됩니다.SEMOPM을 SEMMSL과 동일하게 설정하는 것을 권장합니다. 오라클에서는 100이상의 값으로 설정할 것을 권장 하고 있습니다.


[ 매개변수 - fs.file-max ] Red Hat Linux 서버를 구성하는 과정에서, 사용 가능한 파일 핸들(file handle)의 수가 충분한지 확인하는 것을 매우 중요합니다. 파일 핸들의 최대 개수 설정에 따라 Linux 시스템에서 동시에 오픈할 수 있는 파일의 수가 달라지게 됩니다.
오라클은 전체 시스템의 파일 핸들 수를 최소 65536개 이상으로 설정 할 것을 권장 하고 있습니다.
전체 시스템에서 사용 가능한 파일 핸들의 최대 값을 확인 해보겠습니다.
[2010-12-09 04:06:03]-[root@calmmass:/proc/sys/fs]
# cat /proc/sys/fs/file-max |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
104.857

[ 매개변수 - net.Ipv4.Ip_local_port_range ] 이부분은 새 접속에서 사용할 수 있는 포트의 사용 가능 범위를 확장하는 의미를 가지고 있습니다.
시스템에서 사용하는 포트번호는 /etc/services 파일에 구성 되어있습니다.
[2010-12-09 04:06:24]-[root@calmmass:/proc/sys/fs]
# tail /etc/services
binkp 24554/udp # Binkley
asp 27374/tcp # Address Search Protocol
asp 27374/udp # Address Search Protocol
.. 생략 ..

매개변수의 값을 확인 해보겠습니다. 오라클은 1024 ~ 65000까지 허용하도록 권장 합니다.
[2010-12-09 04:14:10]-[root@calmmass:/proc/sys/net/ipv4]
# cat /proc/sys/net/ipv4/ip_local_port_range |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
32.768 61.000

[ 매개변수 - net.core.rmem_default, net.core.rmem_max ] 일반적인 경우의 대용량 Serving을 위한 설정 합니다. 오라클은 기본적으로 대용량 데이터베이스를 기준으로 하기 때문에 기본 설정 된 값을 변경해야 합니다. 아래와 같은 경우에는 기본 설정 값입니다.
[2010-12-09 04:18:03]-[root@calmmass:/proc/sys/net/core]
# cat /proc/sys/net/core/rmem_default |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
65.535
[2010-12-09 04:18:29]-[root@calmmass:/proc/sys/net/core]
# cat /proc/sys/net/core/rmem_max |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
131.071

[ 매개변수 - net.core.wmem_default, net.core.wmem_max] 소켓 출력 큐의 기본 값과 최대 값을 조정하기 위한 매개변수 입니다. 일반적인 경우의 대용량 Serving을 위한 설정이므로 역시 rmem_default, rmem_max의 값과 동일하게 구성해는 것이 바랍직 합니다. 기본적으로 설정 되어있는 값을 확인 해보겠습니다.
# cat /proc/sys/net/core/wmem_default |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
65.535
[2010-12-09 04:23:05]-[root@calmmass:/proc/sys/net/core]
# cat /proc/sys/net/core/wmem_max |sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1.\2/;ta'
131.071

[ 커널 매개변수 반영 ]
이상으로 매개변수의 용도와 설정값을 확인 하는 방법을 실습 했습니다.
이번에는 커널 매개변수를 오라클 기준으로 변경해서 반영 해보도록 하겠습니다. 기본적으로는 위에 나와있는 설정 파일에 값을 변경 해도 되며, sysctl -w [매개변수명]=value 명령어를 이용 할 수 있습니다. 하지만 이번 문서에서는 리눅스의 장점을 살려 환경설정 파일로 매개변수를 반영 하겠습니다.

오라클(바로가기) 설치 메뉴얼에는 아래와 같이 설정 하길 권장합니다.
cat >> /etc/sysctl.conf <<EOF
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
fs.file-max = 65536
net.ipv4.ip_local_port_range = 1024 65000
EOF
/sbin/sysctl -p

파라매터를 더 추가해보겠습니다. (강추 입니다.)
kernel.shmmax=536870912
kernel.shmmni=4096
kernel.shmall=2097152
kernel.sem=250 32000 100 128
fs.file-max=65536
net.ipv4.ip_local_port_range=1024 65000
net.core.rmem_default=262144
net.core.rmem_max=262144
net.core.wmem_default=262144
net.core.wmem_max=262144



2. Shell Limit 설정

오라클은 Linux 계정 별로 실행되는 프로세스와 열린 파일의 수를 제한하는 것을 권장합니다. 이를 위해, root 계정에서 아래 내용을 /etc/security/limits.conf 설정파일에 oracle10g 라는 특정 프로그램을 제어하는 방법을 설명 하겠습니다.

[참고] /lib/security/pam_limits.so 모듈이 사용할 설정 파일이 /etc/security/limits.conf 파일 입니다. 그중에서 각각 설정에 대해서 아래와 같이 정리 하였습니다.
domain : 제한을 할 대상으로써 사용자 이름이나 그룹 이름, 그리고 와일드 문자를 사용할 수 있습니다.
type : 강하게 제한할 것인지 아니면 어느 정도 여유를 줄 것인지 결정을 합니다.(soft, hard)
item : 제한을 할 항목입니다.
- core : core 파일 사이즈(KB)
- data : 최대 데이터 크기(KB)
- fsize : 최대 파일 사이즈(KB)
- memlock : 최대 locked-in-memory 주소 공간(KB)
- nofile : 한번에 열 수 있는 최대 파일 수
- rss : 최대 resident set size(KB)
- stack : 최대 스택 사이즈(KB)
- cpu : 최대 CPU 점유 시간(MIN)
- nproc : 최대 프로세스 개수
- as : 주소 공간 제한
- maxlogins : 동시 로그인 최대 수
- priority : 사용자 프로세스가 실행되는 우선 순위

[참고] ulimit를 이용하여 리소스를 제한하는 방법입니다. ulimit는 PAM과는 조금 다르게 root계정까지도 제한을 할 수 있습니다. 여기에서 제한에는 두가지 종류가 있습니다.
Soft Limit : 새로운 프로그램이 생성되면 디폴트로 적용되는 제한
Hard Limit : Soft Limit에서 최대 늘릴 수 있는 제한
단, Hard Limit는 root 유저에 의해 조정 가능하지만 무한히 늘리 수 없기 때문에 커널에서 해당 설정 값을 조정 후 늘릴 수 있습니다.


[ oracle10g soft nproc 2047 ] oracle10g 라는 프로그램이 처음 수행시 기본값으로 사용하는 프로세스는 최대 2047로 제한한다는 의미 입니다.
[ oracle10g hard nproc 16384 ] oracld10g 라는 프로그램이 수행시 사용하는 프로세스는 최대 16384로 제한 한다는 의미 입니다.
[ oracle10g soft nofile 1024 ] oracle10g 라는 프로그램이 처음 수행시 기본값으로 사용하는 파일은 최대 1024로 제한 한다는 의미입니다.
[ oracle10g hard nofile 65536 ] oracle10g 라는 프로그램이 수행시 사용하는 파일은 최대 65536으로 제한 한다는 의미 입니다.


[의문점] 어떤 방식으로 해야 이상적인 설정 일까요?
이상적인 설정은 실제로 oracle database가 가동 되고 나서 개수 제한으로 에러가 발생 하지 않게 하는 것이 가장 이상적인 설정이라고 볼 수 있습니다. 그래서 최대한 해당 프로세스의 개수가 어느정도인지 파일의 개수는 평균적으로 어느정도 사용하는지 파악후 설정 해주는것이 바람직합니다.

그럼 특정 프로그램이 사용하는 프로세스의 개수를 테스트 해보도록 하겠습니다.
[2010-12-09 05:38:43]-[root@calmmass:/proc/sys/net/core]
# lsof -p 3094 |wc -l
1370

열려있는 파일 개수 확인 하는 방법
[2010-12-09 05:39:01]-[root@calmmass:/proc/sys/net/core]
# sysctl -a |grep file
fs.file-max = 104857
fs.file-nr = 1995 472 104857

마지막으로 /etc/security/limits.conf 리소스 제한 설정파일에 oracle 설치시 필요한 설정 내역은 아래와 같습니다.
oracle10g soft nproc 2047
oracle10g hard nproc 16384
oracle10g soft nofile 1024
oracle10g hard nofile 65536




Oracle을 각 OS별 설치하면서 느낀 점은 위와 같은 설정 내역이 조금씩 다르다는 점입니다.
그렇다면 이러한 설정 내역을 모두 외우는 것은 무의미하고 어떤 작업에 의해서 설정을 해야 하는지를 먼저 파악하는 것이 우선이라고 생각 했습니다.
각 설정 파일의 역활과 오라클이 구동 되었을때 사용하는 용도를 보면 조금 접근하기기 편하지 않을까 생각 해봅니다.

 

Posted by redkite
, |

- 'PLAN_TABLE' is old version

 

SQL> drop table plan_table;

 

@/oracle/product/10.2.0/db_1/rdbms/admin/utlxplan.sql

Posted by redkite
, |

테이블에 CLOB 타입이 포함된 dmp 파일을 import 하고자 할때.


다음과 같은 오류가 발생할수 있다.

IMP-00017: following statement failed with ORACLE error 959:
...
...
IMP-00003: ORACLE error 959 encountered
ORA-00959: tablespace 'TS_ICMS_DATA' does not exist


import의 경우 컬럼에 CLOB 데이터타입이 포함되어 있을경우는 export받은 테이블의 테이블스페이스 정보와 import 하려고 하는 테이블스페이스가 같아야 한다.

따라서 다음과 같이 테이블 스페이스를 추가한다.

# tablespace 생성
CREATE TABLESPACE TS_ICMS_DATA

DATAFILE '/export/home/oracle/data/ICMSDATA1.dbf' SIZE 1000M;

# 사용자에게 테이블스페이스 지정
CREATE USER test_user IDENTIFIED BY test_pwd DEFAULT TABLESPACE ts_icms_data TEMPORARY TABLESPACE tmp;

# 권한부여
GRANT CONNECT, RESOURCE TO test_user;

Posted by redkite
, |

select tablespace_name, bytes, max_bytes
from user_ts_quotas;

Solution : SQL> Alter user AVS quota unlimited on USR_D;
SQL> alter user AVS quota <size> on USR_D;

Posted by redkite
, |

0003. LOCK object 확인

select do.OWNER, do.OBJECT_NAME, do.OBJECT_ID,
lo.SESSION_ID, lo.ORACLE_USERNAME, lo.OS_USER_NAME,
lo.PROCESS, lo.LOCKED_MODE
from dba_objects do, v$locked_object lo
where do.OBJECT_ID = lo.OBJECT_ID
and do.OWNER = 'IBFUSR'
and do.OBJECT_NAME = 'BT_TAB_SYNC_INFO';

OWNER
------------------------------
OBJECT_NAME
--------------------------------------------------------------------------------
OBJECT_ID SESSION_ID ORACLE_USERNAME
---------- ---------- ------------------------------
OS_USER_NAME PROCESS LOCKED_MODE
------------------------------ ------------ -----------
IBFUSR
BT_TAB_SYNC_INFO
125142 66 IBFUSR
안민혁 2952:852 3

select SID, SERIAL# from v$session where sid = 66;

SID SERIAL#
---------- ----------
66 48801

alter system kill session '66,48801';
ALTER SYSTEM KILL SESSION '66,48801' IMMEDIATE;
ALTER SYSTEM DISCONNECT SESSION '66,48801' IMMEDIATE;

Situation 1

To check objects currently being used, e.g. by a DML statement, before executing a DDL command, you can query v$locked_object as in the example below.


Session A

SQL> connect miles/oracle;
Connected.

SQL> drop table test;

Table dropped.

SQL> create table test (a number);

Table created.

SQL> insert into test values (1);

1 row created.



Session B

SQL> connect / as sysdba
Connected.

SQL> truncate table miles.test;
truncate table miles.test
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified
--> this is expected because miles.test is locked in Session A


SQL>
select do.OWNER, do.OBJECT_NAME, do.OBJECT_ID,
lo.SESSION_ID, lo.ORACLE_USERNAME, lo.OS_USER_NAME,
lo.PROCESS, lo.LOCKED_MODE
from dba_objects do, v$locked_object lo
where do.OBJECT_ID = lo.OBJECT_ID
and do.OWNER = 'MILES'
and do.OBJECT_NAME = 'TEST';


OWNER OBJECT_NAME OBJECT_ID SESSION_ID ORACLE_USERNAME
-------- ------------ ---------- ---------- ------------------------------
OS_USER_NAME PROCESS LOCKED_MODE
-------------------- -------------- -----------
MILES TEST 63754 1079 MILES
oracle 23013 3



From above, you can see miles.test is locked by Oracle user 'MILES' with OS user name 'oracle'.
Session id is 1079, OS process id is 23013.


You can kill the session to release the lock.

SQL> select SID, SERIAL# from v$session where sid = 1079;

SID SERIAL#
---------- ----------
1079 663


SQL> alter system kill session '1079,663';

System altered.



Then the DDL can be executed successfully:

SQL> truncate table miles.test;

Table truncated.

 

Situation 2

If a DDL statement on an object, e.g. create or replace procedure, is hanging because another user is executing the procedure, you can find the blocking session as in the example below.

Using 3 sessions:

  1. Session A: connect as sysdba
  2. Session B: connect as user rob/rob
  3. Session C: connect as user tony/tony


Session A

SQL>
connect / as sysdba
create user rob identified by rob;
grant connect, resource to rob;
create user tony identified by tony;
grant connect, resource to tony;
grant execute on dbms_lock to rob;
grant execute on dbms_lock to tony;



Session B

SQL>
connect rob/rob

create or replace procedure rob_test_p1 is
begin
null;
end;
/

grant execute on rob_test_p1 to tony;



Session C

SQL>
connect tony/tony
begin
rob.rob_test_p1;
dbms_lock.sleep(120);
end;
/



Session A

SQL>
connect / as sysdba

SQL>
select distinct ses.ksusenum sid, ses.ksuseser serial#,
ob.kglnaobj obj_name, ob.KGLNAOWN obj_owner,
ses.KSUUDNAM cur_user
from x$kglpn pn, x$kglob ob, x$ksuse ses
where ob.KGLNAOBJ='ROB_TEST_P1'
and (ob.KGLHDPMD <> 0
or
(ob.KGLHDPMD = 0 and ob.KGLHDLMD not in (0,1))
)
and ob.kglhdadr = pn.kglpnhdl
and pn.kglpnuse = ses.addr;

SID SERIAL# OBJ_NAME OBJ_OWNER CUR_USER
---------- ---------- -------------------- --------------- ------------------
1094 5909 ROB_TEST_P1 ROB TONY


SQL>
select sql_text
from v$sql a, v$session b
where a.sql_id=b.sql_id
and b.serial#=5909;

SQL_TEXT
--------------------------------------------------------------------------------
begin rob.rob_test_p1; dbms_lock.sleep(120); end;



If the DDL is already hanging due to a lock, you can follow below test case to find the lock details.

Session C

SQL> connect tony/tony

SQL>
begin
rob.rob_test_p1;
dbms_lock.sleep(120);
end;
/



Session B

SQL> connect rob/rob

SQL> alter procedure rob_test_p1 compile;
--> This is hanging



Session A

col obj_name format a30
col pin_cnt format 999
col pin_mode format 999
col pin_req format 999
col state format a30
col event format a30
col wait_time format 999999999
col seconds_in_wait format 999999999

SQL>
select distinct ses.ksusenum sid, ses.ksuseser serial#,
ob.kglnaobj obj_name,
pn.kglpncnt pin_cnt, pn.kglpnmod pin_mode, pn.kglpnreq pin_req,
w.state, w.event, w.wait_time, w.seconds_in_Wait
from x$kglpn pn, x$kglob ob, x$ksuse ses, v$session_wait w
where pn.kglpnhdl in (select kglpnhdl from x$kglpn where kglpnreq > 0)
and ob.kglhdadr = pn.kglpnhdl
and pn.kglpnuse = ses.addr
and w.sid = ses.indx
order by seconds_in_wait desc;


SID SERIAL# OBJ_NAME PIN_CNT PIN_MODE PIN_REQ
---------- ---------- ------------------------------ ------- -------- -------
STATE EVENT WAIT_TIME
------------------------------ ------------------------------ ----------
SECONDS_IN_WAIT
---------------
1082 6765 ROB_TEST_P1 3 2 0
WAITING PL/SQL lock timer 0
39

1074 6060 ROB_TEST_P1 0 0 3
WAITING library cache pin 0
27


SQL>
select sql_text
from v$sql a, v$session b
where a.sql_id=b.sql_id
and b.serial#=6765;

SQL_TEXT
--------------------------------------------------------------------------------
begin rob_test_p1; dbms_lock.sleep(120); end;


SQL>
select sql_text
from v$sql a, v$session b
where a.sql_id=b.sql_id
and b.serial#=6060;

SQL_TEXT
--------------------------------------------------------------------------------
alter procedure rob_test_p1 compile

Posted by redkite
, |

SQL> conn /as sysdba
ERROR:
ORA-09925: Unable to create audit trail file
IBM AIX RISC System/6000 Error: 13: Permission denied
Additional information: 9925
ORA-09925: Unable to create audit trail file
IBM AIX RISC System/6000 Error: 13: Permission denied
Additional information: 9925

---------------------------------------------------------------------------

1. init<sid>.ora <parameter:AUDIT_FILE_DEST> 존재 확인

2. $ORACLE_HOME/rdbms/audit 스페이스 확보 full 이면 데이터 임시 폴더로 MOVE

3. $ORACLE_HOME/bin/oracle permission 6755 인지 확인
아니면 chmod 6755 oracle

Posted by redkite
, |

0001. Undo Segment 삭제 방법

ORA-01552 ORA-00376 ORA-01110 ORA-01548 - UNDO tablespace

 

Recently our Helpdesk people configured backup on Payroll server. while running the backup, backup applications locking the writing file.for that issue alert log showing errors like below:

Mon Jul 06 05:07:36 2009
KCF: write/open error block=0x6f6 online=1
file=2 D:\ORACLE9\PRODUCT\PAYROLL\ORADATA\PAYROLL9\UNDOTBS01.DBF
error=27072 txt: 'OSD-04008: WriteFile() failure, unable to write to file
O/S-Error: (OS 33) The process cannot access the file because another process has locked a portion of the file.'
Automatic datafile offline due to write error on
file 2: D:\ORACLE9\PRODUCT\PAYROLL\ORADATA\PAYROLL9\UNDOTBS01.DBF
Mon Jul 06 05:07:36 2009
Errors in file d:\oracle9\product\payroll\admin\payroll9\bdump\payroll9_smon_2700.trc:
ORA-00376: file 2 cannot be read at this time
ORA-01110: data file 2: 'D:\ORACLE9\PRODUCT\PAYROLL\ORADATA\PAYROLL9\UNDOTBS01.DBF'


Immediately we stopped the backup & restarted the database .
Still the Application is not working. Application show error message

 

"ORA-01552: cannot use system rollback segment for non-system tablespace"

then I checked for the corrupted rollback segments

SQL>select segment_name,status,tablespace_name from dba_rollback_segs where status='NEEDS RECOVERY';
SEGMENT_NAME STATUS TABLESPACE_NAME
------------------------------ ---------------- -----------------
_SYSSMU1$ NEEDS RECOVERY UNDOTBS1
_SYSSMU2$ NEEDS RECOVERY UNDOTBS1
_SYSSMU3$ NEEDS RECOVERY UNDOTBS1
_SYSSMU4$ NEEDS RECOVERY UNDOTBS1
_SYSSMU5$ NEEDS RECOVERY UNDOTBS1
_SYSSMU6$ NEEDS RECOVERY UNDOTBS1
_SYSSMU7$ NEEDS RECOVERY UNDOTBS1
_SYSSMU8$ NEEDS RECOVERY UNDOTBS1
_SYSSMU9$ NEEDS RECOVERY UNDOTBS1
_SYSSMU10$ NEEDS RECOVERY UNDOTBS1

then I recreated another tablespace as UNDOTBS2

CREATE UNDO TABLESPACE "UNDOTBS2"
DATAFILE 'D:\ORACLE9\PRODUCT\PAYROLL\ORADATA\PAYROLL9\UNDOTBS02.DBF' SIZE 200M REUSE
AUTOEXTEND ON NEXT 51200K MAXSIZE 800M;

ALTER SYSTEM SET undo_tablespace=UNDOTBS2 SCOPE=BOTH;


Now I try to drop the old UNDO tablespace but it's giving error:

ora-01548 active rollback segment found

Now the issue is resolved but in Alert log we are getting errors like:

Wed Jul 15 11:50:52 2009
SMON: about to recover undo segment 1
SMON: mark undo segment 1 as needs recovery
……..
SMON: about to recover undo segment 10
SMON: mark undo segment 10 as needs recovery


& for some transactions from applications we are getting some more errors:


ORA-00376: file 2 cannot be read at this tme ORA-01110: data file 2: 'D:\ORACLE9\PRODUCT\PAYROLL\ORADATA\PAYROLL9\UNDOTBS01.DBF'


Solution:
1. create pfile from spfile;

2. Add the following line to pfile:


_corrupted_rollback_segments =('_SYSSMU1$','_SYSSMU2$','_SYSSMU3$','_SYSSMU4$',
'_SYSSMU5$','_SYSSMU6$','_SYSSMU7$','_SYSSMU8$','_SYSSMU9$','_SYSSMU10$')

_OFFLINE_ROLLBACK_SEGMENTS=('_SYSSMU1$','_SYSSMU2$','_SYSSMU3$','_SYSSMU4$','_SYSSMU5$','_SYSSMU6$','_SYSSMU7$','_SYSSMU8$','_SYSSMU9$','_SYSSMU10$')

3. comment undo management-Auto


#undo_management=AUTO

4. create spfile from pfile

5. Start the database again:


SQL> STARTUP RESTRICT

6. Drop bad rollback segments


SQL> drop rollback segment "_SYSSMU11$";
Rollback segment dropped.
......
SQL> drop rollback segment "_SYSSMU10$";
Rollback segment dropped.

7. Check again


SQL> select segment_name,status,tablespace_name from dba_rollback_segs where status='NEEDS RECOVERY';

No rows returned

8. DROP TABLESPACE undotbs1 INCLUDING CONTENTS AND DATAFILES ;

9. shutdown immedaite

10. remove added lines & comments from pfile and recreate the spfile

11.startup

Now the issue is resolved.

 

 

SELECT tablespace_name,status FROM dba_rollback_segs;


select segment_name, tablespace_name, status from dba_rollback_segs order by 2;

 

Response 폴더 clientadmin.rsp 파일을 연다.


#------------------------------------------------------------------------------
#Name : ORACLE_HOME
#Datatype : String
#Description: Complete path of the Oracle Home.
#Example : ORACLE_HOME = "/product/10.2.0/client"
#------------------------------------------------------------------------------
ORACLE_HOME="c:\oracle\product\10.2.0\client"

#------------------------------------------------------------------------------
#Name : ORACLE_HOME_NAME
#Datatype : String
#Description: Oracle Home Name. Used in creating folders and services.
#Example : ORACLE_HOME_NAME = "OraClient10ghome1"
#------------------------------------------------------------------------------
ORACLE_HOME_NAME="OraClient10ghome1"

위와 같이 수정한다

그런다음

실행창에서 cmd.exe 입력하여 커멘드 창을 실행 폴더로 이동한다음

setup.exe -silent -responsefile D:\Download\Oracle\Response\clientadmin.rsp

아래와 같이 입력하고 실행 하면 콘솔창에서 oracle 설치된다.

PATCH
/data/oracle/Disk1/stage/products.xml

 

커널 파라미터 설정

# cd /proc/sys/kernel
# echo 2147483648 > shmmax

# vi /etc/sysctl.conf

fs.file-max = 65536
kernel.shmmax = 2147483648
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range= 1024 65000
net.core.rmem_default = 262144
net.core.rmem_max = 262144
net.core.wmem_default = 262144
net.core.wmem_max = 262144

# sysctl -p

참고 : kernel_parameter.rar

-----------------

CentOS 5.2 지원하지 않으므로 레드햇 4 수정.

# vi /etc/redhat-release

Red Hat Enterprise Linux AS release 4 (Taroon)

-----------------

매뉴얼이 제공하는 값과는 다르다.
다른 머신에 설치된 값을 참고했다.

# vi /etc/security/limits.conf

oracle soft nofile 65536
oracle hard nofile 65536
oracle soft nproc 16384
oracle hard nproc 16384

참고 : Shell_Limits.rar

-----------------

# SELINUX=disabled

-----------------

적당히 최신 버전을 설치한다.

# rpm -Uvh setarch-2*
# rpm -Uvh make-3*
# rpm -Uvh glibc-2*
# rpm -Uvh libaio-0*

# rpm -Uvh compat-libstdc++-33-3*
# rpm -Uvh compat-gcc-34-3*
# rpm -Uvh compat-gcc-34-c++-3*
# rpm -Uvh gcc-4*
# rpm -Uvh libXp-1.0.0-8.1.el5.x86_64.rpm
# rpm -Uvh libXp-1.0.0-8.1.el5.i386.rpm

# rpm -Uvh openmotif-2*
# rpm -Uvh compat-db-4*

-------------------

그룹과 유저 생성

# groupadd oinstall
# groupadd dba
# groupadd oper

# useradd -g oinstall -G dba oracle
# passwd oracle

-------------------

설치 디렉토리 생성.
# mkdir -p /u01/app/oracle/product/10.2.0/db_1
# chown -R oracle.oinstall /u01

-------------------

베이스 디렉토리, 디렉토리, 라이브러리 경로 설정

# su - oracle
$ vi .bash_profile

export ORACLE_BASE=/u01/app/oracle
export ORACLE_SID=orcl
export ORACLE_HOME=$ORACLE_BASE/product/10.2.0/db_1
export PATH=$PATH:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib

-------------------

오라클 설치 파일의 압축을 푼다.

$ gzip -d 10201_database_linux_x86_64.cpio.gz
$ cpio -idmvc < 10201_database_linux_x86_64.cpio

-------------------

다음은 오라클 인스톨러를 사일런트 모드로 실행하기 위한 작업이다.

oraInst.loc 파일을 수통 생성한다.

# su -
# cd /etc
# vi oraInst.loc

inventory_loc=/u01/app/oracle/oraInventory
inst_group=

# chown oracle:oinstall oraInst.loc
# chmod 664 oraInst.loc

---------------------

리스폰스 파일 수정, 엔터프라이즈의 다음 항목만 수정했다.

# vi /home/oracle/database/response/enterprise.rsp

ORACLE_HOME=/u01/app/oracle/product/10.2.0/db_1
ORACLE_HOME_NAME=orcl

---------------------

# su - oracle

./runInstaller -silent -responseFile /home/oracle/database/response/enterprise.rsp

글자가 마구 깨져나왔다.

설치 디렉토리를 삭제하고 재성성, 재권한설정을 한다.

$ echo $LANG
$ ko_KR.UTF-8

$ LANG=en_US.UTF-8

재실행, 설치가 완료되었다면 root.sh 실행한다.

$ su -
# /$ORACLE_HOME/root.sh

---------------------

사일런트 모드로 인스톨을 했다면 NetCA DBCA 따로 셋팅해 주어야 한다.
$ vi /home/oracle/database/response/netca.rsp

수정 다음과 같이 실행한다.

$ $ORACLE_HOME/bin/netca /silent /responsefile /local_dir/netca.rsp

DBCA 비슷하다.

$ vi /local_dir/dbca.rsp

$ $ORACLE_HOME/bin/dbca {-progressOnly | -silent} [-cloneTemplate] [-datafileDestination /datafilepath] -responseFile /local_dir/dbca.rsp

---------------------

마지막으로 listener.ora, tnsname.ora 셋팅하고 리스너를 켜봅시다.
$ cd $ORACLE_HOME/network/admin/

예제:
listener.ora tnsnames.ora

$ lsnrctl start

리스너 상태 확인
$lsnrctl status

문자셋을 확인하자.->따로 포스팅 되어있다.

### 신규 롤백 테이블 생성 ###
CREATE UNDO TABLESPACE "UNDOTBS2" DATAFILE '/data1/oradata/COSS/undotbs02.dbf' SIZE 100M REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 200M;

### 신규 테이블로 변경 ###
ALTER SYSTEM SET undo_tablespace=UNDOTBS2 SCOPE=BOTH;

### UNDO 테이블 확인 ###
SELECT tablespace_name,status FROM dba_rollback_segs;

### 온/오프라인 확인 ###
select segment_name, tablespace_name, status from dba_rollback_segs order by 2;

### 테이블 스페이스 드랍 ###
DROP TABLESPACE undotbs1 INCLUDING CONTENTS AND DATAFILES;

### 이전 테이블로 변경하기 위한 테이블스페이스 생성 ###
CREATE UNDO TABLESPACE "UNDOTBS1" DATAFILE '/data1/oradata/COSS/undotbs01.dbf' SIZE 100M REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 200M;

### 이전 테이블로 변경 ###
ALTER SYSTEM SET undo_tablespace=UNDOTBS1 SCOPE=BOTH;

### 온/오프라인 확인 ###
select segment_name, tablespace_name, status from dba_rollback_segs order by 2;

### 신규 테이블 스페이스 드랍 ###
DROP TABLESPACE undotbs2 INCLUDING CONTENTS AND DATAFILES;

Posted by redkite
, |

0002. DBMS_STATS pack 이용

dbms_stats.gather_schema_stats 프로시저를 이용해서 통계 정보를 수집하는 경우 수행 시간이 너무 많이 걸린다는 불만이 종종 있다. 이런 현상은 대부분 다음과 같은 경우에 발생한다.

- 특정 테이블들의 크기가 매우 크다.
- 일부 큰 테이블들은 Partitioning이 되어 있다.

즉 큰 테이블들이 있고 더구나 Partitioning까지 되어 있으니(Global/Partiton Statistics모두 수집해야 하므로) 그만큼 통계 정보 수집에 시간이 걸리기 마련이다. 하지만 Oracle 10g에서는 estimate_percent 파라미터와 method_opt 파라미터의 값이 Oracle에 의해 적절하게 판단되어 통계 정보 생성 시간을 최적화한다. 그렇다면 왜 필요 이상 많은 시간이 걸리는 경우가 발생하는가?

이것은 이 두 파라미터에 다음과 같은 결함이 있기 때문이다.

- estimate_percent 파라미터의 값이 AUTO이다. 즉, Oracle이 테이블의 크기에 따라 적절한 샘플 크기를 선택한다는 의미이다. 대부분의 경우 Oracle은 테이블의 크기에 따라 적절한 값을 찾지만, 간혹 아주 큰 테이블에 대해 100%의 값을 사용하는 경우가 있다.
- method_opt 파라미터의 기본값이 FOR ALL COLUMNS SIZE AUTO이다. 즉 모든 컬럼에 대해 통계정보를 수집하면 히스토그램의 생성 여부는 Oracle이 판단한다. 대부분의 경우 Oracle은 적절한 히스토그램 버킷 크기를 할당하지만, 간혹 불필요하게(가령 Unique Key에 대해) 히스토그램을 생성하는 경우가 있다.

위와 같은 상황이 발생하면 예상보다 지나치게 많은 시간이 걸리게 되는 셈이다.

이런 상황을 해소할 수 있는 방법이 있을까? 가령 다음과 같이 하면...?

dbms_stats.gather_schema_stats(estimate_percent=>10, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');

물론 위의 방법으로 수행 시간 문제는 해결하겠지만, 좋은 방법은 될 수 없다. 만일 크기가 작은 테이블들이 있다면 샘플 크기가 작으면 왜곡된 통계 정보가 수집될 수 있다. 만일 특정 테이블에 대해서는 모든 컬럼(ALL COLUMNS)에 대해 통계 정보를 수집해야 한다면? 또는 특정 테이블의 특정 컬럼에 대해서는 히스토그램 크기를 주고 싶다면?

그렇다고 테이블 레벨로 일일이 dbms_stats.gather_table_stats를 호출하는 것은 너무나 지겨운 일이다.

그래서 보통 다음과 같은 트릭을 종종 사용한다.(편의상 정확한 문법은 생략)

-- 특정 테이블 통계 정보 변경을 막음
dbms_stats.lock_table_stats(user, 'TABLE1');

exec dbms_stats.gather_schema_stats(ownname=>'ORANGE', ESTIMATE_PERCENT=> 10, BLOCK_SAMPLE=>TRUE, DEGREE=> 8, CASCADE=>TRUE);

-- 스키마 레벨로 통계 정보 수집
dbms_stats.gather_schema_stats(user);

-- 통계 정보 활성화 후 이 테이블만 다시 통계 정보 수집
dbms_stats.unlock_table_stats(user, 'TABLE1');
dbms_stats.gather_table_stats(user,'TABLE', estimate_percent=>10, method_opt=>'FOR ALL INDEXED COLUMNS SIZE AUTO');

begin

dbms_stats.gather_table_stats(ownname => 'PS_MOM', tabname => 'ETL_JOB_LOG_TBL', estimate_percent=>10)

end;

/

begin

dbms_stats.gather_index_stats(ownname => 'PS_MOM', indname => 'IDX_ETL_LOG_ID');

end;

/
위와 같이 하면 Schema 레벨로 대부분의 테이블에 대해 통계 정보를 수집한 후 특정 문제가 되는 테이블에 대해서만 별도로 통계 정보를 수집할 수 있다.

지저분한 트릭같지만 매우 유용한 방법이다.

Oracle 11g에서는 "Preference"라는 새로운 개념을 통해 위와 같은 불편을 일시에 해소하고 있다. Oracle 11g에서라면 다음과 같이 훨씬 직관적이고 깔끔한 방법을 쓸 수 있다.

-- 아래와 같이 한번만 설정
dbms_stats.set_table_prefs(user,'TABLE1', 'ESTIMATE_PERCENT', '10');
dbms_stats.set_table_prefs(user,'TABLE1','METHOD_OPT', 'FOR ALL INDEXED COLUMNS SIZE AUTO');

-- Schema 레벨에서 통계 정보 수집
dbms_stats.gather_schema_stats(user);

즉, 특정 테이블별로 Preference(선호도)를 저장할 수 있어서 10g에서와 같은 부자연스러운 트릭은 불필요한 것이다. 11g에서 가장 마음에 드는 New Feature중 하나이다.

Posted by redkite
, |

오라클을 통해 작업할

insert시점에서 정상적으로 인덱싱이 되지 않는 경우가 발생한다.

특히 결합인덱스를 많이 사용하고 있는 경우 발생될 확률이 높다.

 

이런경우 오라클의 Analyzed 통해서 해결이 가능하고

어느정도의 실행속도를 향상 시킬 수있다.

(실제 오라클사에서도 3개월에 한번씩은 Analyze 실행하라 권고하고 있다.)

 

[Analyzed 확인 방법]

select table_name, num_rows, to_char(last_analyzed, 'yyyymmdd') from user_tables

select index_name, num_rows, to_char(last_analyzed, 'yyyymmdd') from user_indexes

 

ex) select table_name, num_rows, to_char(last_analyzed, 'yyyymmdd') from user_tables;

TABLE_NAME NUM_ROWS TO_CHAR(
------------------------------ ---------- --------
ABS_TYPE 38
20040101

ANNIVERS 183 20040101
APPRFLDRHISTORY 570
20040101
APPRFOLDER 16885
20040101
APPRFOLDER_ERR 3670
20040101
APPRFORM 359
20040101
.
.
.
USR_INFO_ADMIN 0
20040101
VAR_DEPT_INFO 0
20040101
VIEW_TYPE 0
20040101
WASTEBOX 0
20040101
ZIP_CODE 44195
20040101

252 rows selected.

 

참고 : desc user_tables 에서 보통 num_rows 로도 확인 가능

 

 

[특정 Table Analyze 하는 방법]

 

analyze table document compute statistics

ex) DOCUMENT Table Analyze

 

analyze index xpkdocbox compute statistics

ex) XPKDOCBOX Index Analyze

 

[전체 Table Analyze 하는 간단한 방법]

 

1. vi analyze_all.sql
select 'analyze table || table_name || estimate statistics;' from user_tables

 

2. @analyze_all.sql

 

3. set heading off
set echo off
set feedback off
set pagesize 300 (line
300 미만일 경우)
spool analyze_table.sql
/
spool off

 

4. vi analyze_table.sql
필요없는 Line 제거 정리

 

5. @analyze_table.sql

 


[
전체 Index Analyze 하는 간단한 방법]

 

 

1. vi analyze_all.sql
select 'analyze '||object_type||' ps_mom.'||object_name||' compute statistics; '

from dba_objects

where owner = 'PS_MOM'

and object_type in('TABLE','INDEX')

/

 

2. @analyze_all.sql

 

3. set heading off
set echo off
set feedback off
set pagesize 300 (line
300 미만일 경우)
spool analyze_index.sql
/
spool off

 

4. vi analyze_index.sql
필요없는 Line 제거 정리

 

5. @analyze_index.sql

'01.오라클 > 008.DB 통계 및 공간 관리' 카테고리의 다른 글

[오라클]SHRINK SPACE 관리  (0) 2012.12.19
[오라클]DBMS STAT PACK 이용  (0) 2012.12.19
Posted by redkite
, |

0017. INDEX 생성 가이드라인

☞ 12-5 b-tree index

* 특성
1. 컬럼값이 같으면 rowid 순으로 정렬
2. null에는 인덱스가 생성되지 않는다.

* 인덱스에 대한 DML 작업 효과

Index 에는 pctused파라미터가 없다.


이말은 인덱스를 삭제하고 남은 공간을 다시 활용하지 않는 다는 뜻이다.
이런 이유 때문에 인덱스는 주기적으로 정리 되어야 하며 그렇게 하지 않으면 인덱스의 사이즈는 점점 증가 한다.

☞ 12-7 bitmap index

index를 경유하면 모든 데이터를 읽지않고 원하는 범위의 데이터만 읽기 때문에 빠른 성능을 보장받을 수 있다. 하지만 그범위가 아주 넓은 경우에는 오히려 더 나쁜 성능을 나타내게 된다. 이처럼 B*tree inex의 단점은 cardinality가 낮은 속성에 대하여 취약하는 것이다.
(색깔의 종류가 적을 수록 좋다)

☞ 12-9 비트리 인데스와 비트맵 인덱스 비교

비트리 인덱스는 카디널리티가 높은 것에 유리하고 비트맵은 낮은것에 유리 함. 그리고 비트맵 인덱스는 비트맵 세그먼트 수준의 잠금을 사용하기 때문에 비트맵 인덱스의 키열을 갱신하면 더 많은 비용이 들지만 B트리 인덱스에서는 테이블의 각행에 해당하는 항목을 잠금으로 update 할 때 유리 . 비트맵은 부울 연산 식을 사용해서 부울 수식에 유리.
OLTP(게시판이나 수시로 바끼는 것)환경에서는 B트리 인덱스가 유리. 대형 정적 테이블에서 복합 질의 사용하는 데이터 웨어하우스 환경에서는 비트맵이 유리.

☞ 12-10 일반 B 트리 인덱스 생성

create index hr.employees_last_name_indx
on hr.employees(last_name)
pctfree 30
storage (initial 200k next 200k
pctincrease 0 maxextents 50)
tablespace indx;


last_name 열을 사용하여 employees 테이블에 인덱스를 생성



주의) 밑에 tablespace indx;를 지정하지 않으면 동시에 사용자가 접속하면 index를 사용하면 lock이 걸리기 때문에 지정해 줘야함


☞ 12-13 인덱스 생성시 가이드라인

create index emp_hiredate on emp(hiredate) pctfree 30 initrans 10;

1. 인덱스를 사용하면 쿼리 속도는 빨라지나 DML 작업속도는 느려진다.

2. 별도의 테이블 스페이스에 인덱스 세그먼트를 둔다.

3. 대용량 테이블에 인덱스 생성시 nologging 옵션을 쓰는게 좋다.

이유) 큰 인덱스의 경우 리두로그파일 생성을 방지하면 성능을 상당히 향상시킬수 있으므로

4. 인덱스 생성시 initrans(각 블록에서 미리 할당하는 트랜잭션 항목수) 값을 테이블 보다 많이 줘야 한다.

이유) 인덱스 항목은 자신이 인덱스하는 행보다 작기 때문에 인덱스 블록은 블록마다 많은 항목을 포함 해당 테이블보다 인덱스에 대한 initrans가 높아야 한다.

☞ 12-15 비트맵 인덱스 생성

create bitmap index orders_region_id_idx
on orders(region_id)
pctfree 30
storage(initial 200k next 200k
pctincrease 0 maxextents 50)
tablespace indx;

 

☞ 12-18 인덱스 저장 영역 매개변수 변경

alter index employees_last_name_idx
storage(next 400k
maxextents 100);

 

☞ 12-20 인덱스 공간 할당 및 할당 해제

alter index orders_region_id_idx
allocate extent (size 200k
datafile '/disk6/indx01.dbf');

 

alter index orders_id_idx
deallocate unused;


테이블에 대량의 삽입 작업 전에 인덱스에 확장영역을 추가 할수 있으며 확장 영역을 추가하면 인덱스가 동적으로 할당 되어 성능 저하를 방지 할수 있다.


☞ 12-21 인덱스 재구축

alter index orders_region_id_idx rebuild
teablespace indx02;


* 기존 인덱스를 데이터 소스로 사용하여 인덱스 구축
* 기존 인덱스를 사용하면 다시 구축할 필요가 없으므로 성능 향상
* 새 인덱스를 구축할 충분한 공간 필요
* 새 인덱스를 구축하는 동안 quary에서 기존 인덱스를 사용 가능

@ 재구축이 필요한 상황

1. 인덱스가 있는 테이블 스페이스를 이동할때
2. 인덱스 테이블을 alter table ........ move tablespace 명령을 사용하여 이동

SQL> select table_name, tablespace_name from user_tables
2 where table_name='EMP';

TABLE_NAME TABLESPACE_NAME
------------------------------ ------------------------------
EMP USERS

SQL> create index emp_ename
2 on emp(ename);

인덱스가 생성되었습니다.

SQL> alter table emp
2 move tablespace tools;

테이블이 변경되었습니다.

SQL> select ename
2 from emp
3 where ename='SCOTT';


select ename
*
1행에 오류:
ORA-01502: 인덱스 'SCOTT.EMP_ENAME'또는 인덱스 분할영역은 사용할 수 없은
상태입니다


SQL> alter index emp_ename rebuild;

인덱스가 변경되었습니다.

SQL> select ename
2 from emp
3 where ename='SCOTT';

ENAME
----------
SCOTT

SQL> @p.sql


file toto.sql(이)가 기록되었습니다

테이블이 잘렸습니다.

1* select ename
1* explain plan set statement_id='MyTest' for select ename

해석되었습니다.


Query Plan
---------------------------------------------------------------
SELECT STATEMENT Cost =
INDEX RANGE SCAN EMP_ENAME NON-UNIQUE

실습2)

1* alter index emp_ename rebuild reverse
SQL> /

인덱스가 변경되었습니다.

SQL> select index_name, index_type
2 from user_indexes;

INDEX_NAME INDEX_TYPE
------------------------------ ---------------------------
C_ID_DATE NORMAL
C_ID_PK NORMAL
DEPT200_DEPTNO_PK NORMAL
EMP21_EMPNO_PK NORMAL
EMP22_EMPNO_PK NORMAL
EMP_BIT_JOB BITMAP
EMP_ENAME NORMAL/REV
EMP_HIREDATEON NORMAL
SYS_C003006 NORMAL
SYS_IL0000030314C00001$$ LOB

10 개의 행이 선택되었습니다.

bitmap 도 될까 ?

☞ 12-23 index 온라인으로 재구축

alter index ordes_id_idx rebuild online;

9i 에서 인덱스 재 구축 작업 동안 동시에 DML 작업 수행할수있는것

SQL> update test1
2 set sal=0
3 where id=9993;

2 행이 갱신되었습니다.

 

다른세션에서 인덱스를 생성하려하거나 재구축 또는 삭제하려하는게 안된다.

SQL> alter index test1_sal rebuild reverse;
alter index test1_sal rebuild reverse
*
1행에 오류:
ORA-00054: 자원이 사용중이고, NOWAIT가 지정되어 있습니다


SQL> /

인덱스가 변경되었습니다.

SQL> /
alter index test1_sal rebuild reverse
*
1행에 오류:
ORA-00054: 자원이 사용중이고, NOWAIT가 지정되어 있습니다


SQL> drop index test1_sal;
drop index test1_sal
*
1행에 오류:
ORA-00054: 자원이 사용중이고, NOWAIT가 지정되어 있습니다


SQL> /

인덱스가 삭제되었습니다.

SQL> create index test1_sal
2 on test1(sal);
on test1(sal)
*
2행에 오류:
ORA-00054: 자원이 사용중이고, NOWAIT가 지정되어 있습니다

다음 실습은 sh 유져에서 작업할것이다. sh 계정을 활성화시키시요 ( 유쌤 ^^)

SQL> create index sales_amount_sold
2 on sales(amount_sold);

인덱스가 생성되었습니다.

다른세션에서

SQL> update sales
2 set amount_sold=0
3 where prod_id=250;

475 행이 갱신되었습니다.

책에 나온 내용과 테스트가 틀리다. 책이 틀린것 같다. ( 또 오라클이 오버했네요. 안되는거 된다고 하고...)

그런데 재구축은 책이 맞습니다.

먼저 online 을 붙이지 않고 실습하고

alter index slaes_amount_sold rebuild ;

다른세션에서

SQL> update sales
2 set amount_sold=0
3 where prod_id=250;

475 행이 갱신되었습니다.

online 붙이고 실습하라

alter index slaes_amount_sold rebuild online;

SQL> update sales
2 set amount_sold=0
3 where prod_id=250;

475 행이 갱신되었습니다.

☞ 12-23 index 유효성 검사

SQL> analyze index sales_amount_sold validate structure;

SQL> select blocks, pct_used, distinct_keys
2 , lf_rows, del_lf_rows
3 from index_stats;

BLOCKS PCT_USED DISTINCT_KEYS LF_ROWS DEL_LF_ROWS
---------- ---------- ------------- ---------- -----------
2816 90 6755 1016271 0

del_lf_rows 와 lf_rows 의 비율이 30% 를 초과하는 경우에 인덱스를 재구성한다


☞ 12-23 사용되는 index 와 안되는 인덱스 구별 (9i 뉴피쳐)

SQL> alter index sales_amount_sold monitoring usage;

인덱스가 변경되었습니다.

SQL> select * from v$object_usage;

다른세션에서

select *
from sales
where amount_sold=250
/

그리고 다시

SQL> select * from v$object_usage;

보면 use 가 yes 로 나올것이다.

☞ 12-24 인덱스 병합

alter index orders_id_idx coalesce;

 

coalesce 작업을 수행하기 전 첫번때 두개의 최하위 블록은 50%가 채워진 상태이고, 인덱스가 단편화 되었으므로 병합하여 하나로 합친다.

☞ 12-25 인덱스 및 유효성 검사

ANALYZE INDEX orders_region_id_idx
VALIDATE STRUCTURE;

인덱스를 분석하여 다음을 수행
* 모든 인덱스 블록에 대해 손상된 블록을 확인. 이명령을 수행해도 인덱스 항목이 테이블의 데이터에 대응되는지 여부는 확인되니 않음

* index_stats 뷰를 인덱스 정보로 채움

SELECT (del_lf_rows_len/ lf_lows_len) * 100 as balancing from index_stats;

15% 만 rebuilding 함

☞ 12-29 사용 되지 않은 익덱스 식별

*인덱스 사용에 대한 모니터를 시작하는 방법

ALTER INDEX hr.dept_id_idx
MONITORING USAGE

* 인덱스 사용에 대한 모니터를 중지하는 방법

ALTER INDEX hr.dept_id_idx
NOMONITORING USAGE

==>인덱스 사용에 대한 통계를 수집하여 V$OBJECT_USAGE에 표시

SELECT index_name, used from V$OBJECT_USAGE;

Posted by redkite
, |

0016. Oracle 8i Nosegment Index vs. Oracle 11g Invisible Index

Oracle 11g New Feature에 새로운 이야기들을 많이 들었을 것이다.
이중 유난히 나의 관심을 끄는 한 가지가 Invisiblie Index이다. Invisilble Index란 말 그대로 "보이지" 않는 인덱스를 의미한다. 더 정확하게 말하면 인덱스 세그먼트로서 물리적으로 존재는 하지만 Optimizer에게는 보이지 않는 인덱스를 의미한다.

테이블에 새로운 인덱스를 추가하면 Optimizer의 비용(Cost) 계산에 영향을 주어 기존 쿼리의 실행 계획에 영향을 주게 된다. 물론 이것은 바람직한 것이고, 인덱스의 존재 이유이기도 하다.

하지만, 간혹 인덱스를 추가했을 때 이 인덱스로 인해 성능 개선이 이루어질 것인지만을 테스트해고 싶은 경우가 있다. 이런 경우에는 어떻게 해야할까?

잘 알려지지 않은 사실이지만, Oracle 8i에서 Virtual Index 기능이 추가되었다. Virtual Index란 말 그대로 가상의 인덱스로 실제로는 인덱스가 존재하지 않지만, 인덱스가 존재하는 것처럼 데이터를 조작하는 것을 의미한다. 이런 의미에서 흔히 Fake Index(가짜 인덱스)라고 부르기도 한다. 아래 테스트 스크립트를 보자.

select * from v$version;
--------------------------------------------------------
BANNER
Oracle8i Enterprise Edition Release 8.1.7.0.0 - 64bit Production
PL/SQL Release 8.1.7.0.0 - Production
CORE 8.1.7.0.0 Production
TNS for HPUX: Version 8.1.7.0.0 - Development
NLSRTL Version 3.4.1.0.0 - Production

-- Table 생성
create table t_noseg(id int, id2 int);

-- Clustering Factor를 달리 하기 위해 id, id2의 순서를 다르게 삽입한다.
insert into t_noseg
select rownum, decode(mod(rownum,2),1,50000-rownum+1,rownum) from all_objects t1, all_objects t2
where rownum <= 50000

commit;

-- Virtual Index를 생성한다. (NOSEGMENT 속성 부여)
-- id 컬럼에 대한 인덱스는 Clustering Factor가 매우 우수하다.
-- 하지만 id2 컬럼에 대한 인덱스는 Clustering Factor가 매우 불량하다.
create index t_noseg_idx on t_noseg(id) nosegment;
create index t_noseg_idx2 on t_noseg(id2) nosegment;

-- 통계 정보를 생성한다.
exec dbms_stats.gather_table_stats(user,'T_NOSEG', cascade=>true);

-- Virtual Index는 실제로는 사용되지 않으며 실행 계획을 테스트하는 목적으로만 사용된다.
-- _use_nosegment_indexes 값을 true로 변경하면 실행 계획에 반영할 수 있다.
alter session set "_use_nosegment_indexes" = true;

-- 다음과 같이 id 컬럼에 대해 가상의 인덱스를 선택하는 실행 계획이 수립됨을 확인할 수 있다.
-- Cost가 4이고, Index는 Analyze가 되지 않았다는 사실에 주목하자.
select * from t_noseg
where id between 1 and 100;

SELECT STATEMENT CHOOSE-Cost : 4
TABLE ACCESS BY INDEX ROWID MAXGAUGE.T_NOSEG(1) Analyzed : 20080113
INDEX RANGE SCAN MAXGAUGE.T_NOSEG_IDX(NU) (ID) NOT ANALYZED

-- id2 컬럼에 대해서도 역시 인덱스를 선택하는 실행 계획이 수립된다.
-- 하지만, Clustering Factor에 의한 비용 증가는 계산되지 않는다.
select * from t_noseg
where id2 between 1 and 100;

SELECT STATEMENT CHOOSE-Cost : 4
TABLE ACCESS BY INDEX ROWID MAXGAUGE.T_NOSEG(1) Analyzed : 20080113
INDEX RANGE SCAN MAXGAUGE.T_NOSEG_IDX2(NU) (ID2) NOT ANALYZED

-- 세그먼트가 존재하는가?
select count(*) from dba_segments where segment_name = 'T_NOSEG_IDX';
----------------------------------------------------------------
0

select count(*) from dba_objects where object_name = 'T_NOSEG_IDX';
----------------------------------------------------------------
1

위의 테스트 결과를 보면 다음과 같은 사실을 추론할 수 있다.
- Virtual Index는 실제로는 세그먼트가 생성되지 않으며, 딕셔너리에만 존재하는 인덱스이다.
- 따라서 실행 계획을 추측해보는데는 도움이 되지만, 실제로 실행에 반영할 수는 없다.
- 실제 세그먼트가 존재하지 않기 때문에 통계 정보를 수집할 수 없다. 따라서 Clustering Factor와 같은 중요한 요소는 계산되지 않는다. 이는 비용 계산에 오류를 초래할 수 있다.

Virtual Index는 오라클 내부적으로만 사용될 목적으로 만들어졌으며 대중적으로 공개가 되어 있지 않다.

Oracle 11g는 Virtual Index를 계승 발전시켜서 Invisible Index라는 전혀 새로운 개념을 소개하고 있다. Invisible Index는 Virtual Index와는 달리 실제로 세그먼트 형태로 존재하는 인덱스이다. 다만 Optimizer에게 보이지 않을 뿐이다. 아래 테스트 스크립트를 보자.

-- Table 생성
create table t_invisible(id int, id2 int);

-- 역시 Clustering Factor를 달리 하기 위해 id, id2의 순서를 다르게 삽입한다.
insert into t_invisible
select rownum, decode(mod(rownum,2),1,50000-rownum+1,rownum) from all_objects t1, all_objects t2
where rownum <= 50000

commit;

-- Invisible Index를 생성한다.
create index t_invisible_idx on t_invisible(id) invisible;
create index t_invisible_idx2 on t_invisible(id2) invisible;

-- Invisible Index를 사용하게끔 변경한다. 이렇게 해야만 통계 정보가 수집된다.
alter session set optimizer_use_invisible_indexes=true;

-- 통계 정보 수집
exec dbms_stats.gather_table_stats(user,'T_INVISIBLE', cascade=>true);

-- 다음과 같이 id 컬럼에 대해 가상의 인덱스를 선택하는 실행 계획이 수립됨을 확인할 수 있다.
-- Cost가 3이고, Index가 Analyze되었음에 유의하자.
select * from t_invisible
where id between 1 and 100;

SELECT STATEMENT ALL_ROWS-Cost : 3
TABLE ACCESS BY INDEX ROWID UKJA.T_INVISIBLE(1)
INDEX RANGE SCAN UKJA.T_INVISIBLE_IDX (ID)

-- id2 컬럼에 대해서는 Full Table Scan을 사용하다.
-- id2 컬럼은 Clustering Factor가 매우 불량하기 때문에 이것이 비용에 반영된 결과이다.
select * from t_invisible
where id2 between 1 and 100;

SELECT STATEMENT ALL_ROWS-Cost : 21
TABLE ACCESS FULL UKJA.T_INVISIBLE(1)

-- 실제 id2 컬럼에 대해 인덱스를 사용하면 비용이 어떻게 계산되지는 확인해보면 아래와 같다.
-- 비용이 102로 Full Table Scan보다 오히려 비싸게 계산되는 것을 확인할 수 있다.
select /*+ index(t_invisible t_invisible_idx2) */* from t_invisible
where id2 between 1 and 100;

SELECT STATEMENT ALL_ROWS-Cost : 102
TABLE ACCESS BY INDEX ROWID UKJA.T_INVISIBLE(1)
INDEX RANGE SCAN UKJA.T_INVISIBLE_IDX2 (ID2)

-- 세그먼트가 존재하는가?
select count(*) from dba_segments where segment_name = 'T_INVISIBLE_IDX';
-----------------------------------------------------------------
1

Invisible Index는 Virtual Index와는 달리 실제로 존재하는 인덱스이고 따라서 통계 정보가 수집된다. 따라서 보다 정확한 테스트를 수행할 수 있다. 테스트후 반영여부가 결정되면 다음과 같이 손쉽게 Visible Index로 전환할 수 있다.

alter index t_invisible_idx visible;

위의 간단한 테스트 결과를 보면 Invisible Index가 기존의 Virtual Index에 비해서 훨씬 유용한 기능을 제공하는지 잘 알 수 있다. 아무쪼록 많이 활용되었으면 한다.

(참고) Invisible Index가 존재하는 테이블/인덱스에 대해 통계 정보를 수집하려고 하면 ORA-904: Invalid Column 에러가 발생한다. 이것은 11g R1의 버그이다. 패치가 나오기 전까지는 optimizer_use_invisible_indexes 값을 true로 변경한 후 통계 정보를 수집해야 한다.

Posted by redkite
, |

0015. 데이터베이스 아키텍쳐

1. 아키텍처 개관

가. oracle 아키텍처

Database : 데이터 집합(Datafile, Redo Log File, Control File 등)

Instance : SGA 공유 메모리 영역과 이를 액세스하는 프로세스 집합

기본적으로 하나의 인스턴스가 하나의 데이터베이스만 액세스하지만, RAC(Real Application Cluster) 환경에서는 여러 인스턴스가 하나의 데이터베이스를 액세스할 수 있다. 하나의 인스턴스가 여러 데이터베이스를 액세스할 수는 없다.

나. SQL Server 아키텍처

데이터베이스 하나를 만들 때마다 주(Primary 또는 Main) 데이터 파일과 트랜잭션 로그 파일이 하나씩 생기는데, 전자는 확장자가 mdf이고 후자는 ldf이다. 저장할 데이터가 많으면 보조(Non-Primary) 데이터 파일을 추가할 수 있으며, 확장자는 ndf이다.

2. 프로세스

프로세스는 서버 프로세스(Server Processes)와 백그라운드 프로세스(Background Processes) 집합으로 나뉨. 서버 프로세스는 전면에 나서 사용자가 던지는 각종 명령을 처리하고, 백그라운드 프로세스는 뒤에서 묵묵히 주어진 역할을 수행한다.(SQL Server는 쓰레드(Thread) 기반 아키텍처)

가. 서버 프로세스(Server Processes)

서버 프로세스는 사용자 프로세스와 통신하면서 사용자의 각종 명령을 처리하며, SQL Server에선 Worker 쓰레드가 같은 역할을 담당한다.

SQL을 파싱하고 필요하면 최적화를 수행하며, 커서를 열어 SQL을 실행하면서 블록을 읽고, 읽은 데이터를 정렬해서 클라이언트가 요청한 결과집합을 만들어 네트워크를 통해 전송하는 일련의 작업을 모두 서버 프로세스가 처리.

스스로 처리하도록 구현되지 않은 기능, 이를테면 데이터 파일로부터 DB 버퍼 캐시로 블록을 적재하거나 Dirty 블록을 캐시에서 밀어냄으로써 Free 블록을 확보하는 일, 그리고 Redo 로그 버퍼를 비우는 일 등은 OS, I/O 서브시스템, 백그라운드 프로세스가 대신 처리하도록 시스템 Call을 통해 요청. Oracle에는 전용/공유 서버 방식 두 가지가 있다.

1) 전용 서버(Dedicated Server) 방식

서버 프로세스가 단 하나의 사용자 프로세스를 위해 전용(Dedicated) 서비스를 제공.

SQL을 수행할 때마다 연결 요청을 반복하면 서버 프로세스의 생성과 해제도 반복하게 되므로 DBMS에 매우 큰 부담을 주고 성능을 크게 떨어뜨림(OLTP성 애플리케이션에선 Connection Pooling 기법을 필수적으로 사용해야 한다.)

 

2) 공유 서버(Shared Server) 방식

하나의 서버 프로세스를 여러 사용자 세션이 공유하는 방식으로서 여러 개의 서버 프로세스를 띄어 놓고 이를 공유해서 사용.

사용자 프로세스는 서버 프로세스와 직접 통신하지 않고 Dispatcher 프로세스를 거친다.

사용자 명령이 Dispatcher에게 전달되면 Dispatcher는 이를 SGA에 있는 요청 큐(Request Queue)에 등록.

이후 가장 먼저 가용해진 서버 프로세스가 요청 큐에 있는 사용자 명령을 꺼내서 처리하고

그 결과를 응답 큐(Response Queue)에 등록한다.

응답 큐를 모니터링하던 Dispatcher가 응답 결과를 발견하면 사용자 프로세스에게 전송해 준다.

 

나. 백그라운드 프로세스(Background Processes)

3. 파일 구조

가. 데이터 파일

1) 블록(=페이지)

대부분 DBMS에서 I/O는 블록 단위.(Oracle은 '블록(Block)', SQL Server는 '페이지(Page)')

Oracle은 2KB, 4KB, 8KB, 16KB, 32KB, 64KB의 다양한 블록 크기를 사용가능

SQL Server에선 8KB 단일 크기를 사용한다.

*블록 단위로 I/O 한다는 것은, 하나의 레코드에서 하나의 칼럼만을 읽으려 할 때도 레코드가 속한 블록 전체를 읽게 됨을 뜻함

SQL 성능을 좌우하는 가장 중요한 성능지표는 액세스하는 블록 개수.

 

2) 익스텐트(Extent)

테이블 스페이스로부터 공간을 할당하는 단위. 테이블이나 인덱스에 데이터를 입력하다가 공간이 부족해지면 해당 오브젝트가 속한 테이블 스페이스(물리적으로는 데이터 파일)로부터 추가적인 공간을 할당받는데, 이때 정해진 익스텐트 크기의 연속된 블록을 할당받는다.

익스텐트 내 블록은 논리적으로 인접하지만, 익스텐트끼리 서로 인접하지는 않는다.

(Oracle은 다양한 크기의 익스텐트를 사용하지만, SQL Server에선 8개 페이지의 익스텐트만을 사용.)

Oracle은 한 익스텐트에 속한 모든 블록을 단일 오브젝트가 사용하지만, SQL Server에서는 2개 이상 오브젝트가 나누어 사용할 수도 있다.

SQL Server는 다음 2가지 타입의 익스텐트를 사용.

  • 균일(Uniform) 익스텐트 : 64KB 이상의 공간을 필요로 하는 테이블이나 인덱스를 위해 사용되며, 8개 페이지 단위로 할당된 익스텐트를 단일 오브젝트가 모두 사용한다.
  • 혼합(Mixed) 익스텐트 : 한 익스텐트에 할당된 8개 페이지를 여러 오브젝트가 나누어 사용하는 형태다. 모든 테이블이 처음에는 혼합 익스텐트로 시작하지만 64KB를 넘으면서 2번째부터 균일 익스텐트를 사용하게 된다.

 

3) 세그먼트

세그먼트는 테이블, 인덱스, Undo처럼 저장공간을 필요로 하는 데이터베이스 오브젝트다. (한개 이상의 익스텐트 사용)

((ex 테이블,인덱스 )

다른 오브젝트는 세그먼트와 1:1 대응 관계를 갖지만 파티션은 1:M 관계를 갖음.

파티션 테이블(또는 인덱스)을 만들면, 내부적으로 여러 개의 세그먼트가 만들어진다.

한 세그먼트는 자신이 속한 테이블 스페이스 내 여러 데이터 파일에 걸쳐 저장될 수 있음.

세그먼트에 할당된 익스텐트가 여러 데이터 파일에 흩어져 저장되는 것이며, 그래야 디스크 경합을 줄이고 I/O 분산 효과를 얻을 수 있다.

 

4) 테이블 스페이스

테이블 스페이스는 세그먼트를 담는 콘테이너로서, 여러 데이터 파일로 구성된다.

사용자는 세그먼트를 위한 테이블 스페이스를 지정할 뿐, 실제 값을 저장할 데이터 파일을 선택하고 익스텐트를 할당하는 것은 DBMS의 몫. 각 세그먼트는 정확히 한 테이블 스페이스에만 속하지만, 한 테이블 스페이스에는 여러 세그먼트가 존재할 수 있다.

특정 세그먼트에 할당된 모든 익스텐트는 해당 세그먼트와 관련된 테이블 스페이스 내에서만 찾아진다. (한 세그먼트가 여러 테이블 스페이스에 걸쳐 저장될 수는 없음.)

한 세그먼트가 여러 데이터 파일에 걸쳐 저장될 수는 있다. 한 테이블 스페이스가 여러 데이터 파일로 구성되기 때문.

 

 

나. 임시 데이터 파일

임시(Temporary) 데이터 파일은 특별한 용도로 사용된다. 대량의 정렬이나 해시 작업을 수행하다가 메모리 공간이 부족해지면 중간 결과집합을 저장하는 용도다. ( Redo 정보를 생성하지 않기 때문에 나중에 파일에 문제가 생겼을 때 복구되지 않는다. 따라서 백업할 필요도 없다.)

Oracle에선 임시 테이블 스페이스를 여러 개 생성해 두고, 사용자마다 별도의 임시 테이블 스페이스를 지정해 줄 수도 있다.

create temporary tablespace big_temp tempfile '/usr/local/oracle/oradata/ora10g/big_temp.dbf' size 2000m;

alter user scott temporary tablespace big_temp;

SQL Server는 단 하나의 tempdb 데이터베이스를 사용한다. tempdb는 전역 리소스로서 시스템에 연결된 모든 사용자의 임시 데이터를 여기에 저장한다.

다. 로그 파일

DB 버퍼 캐시에 가해지는 모든 변경사항을 기록하는 파일

Oracle : 'Redo 로그'

SQL Server는 '트랜잭션 로그'.

변경된 메모리 버퍼 블록을 디스크 상의 데이터 블록에 기록하는 작업은 Random I/O 방식으로 이루어지기 때문에 느리다.

반면 로그 기록은 Append 방식으로 이루어지기 때문에 상대적으로 매우 빠르다.

DBMS는 버퍼 블록에 대한 변경사항을 건건이 데이터 파일에 기록하기보다 우선 로그 파일에 Append 방식으로 빠르게 기록하는 방식을 사용한다. 그러고 나서 버퍼 블록과 데이터 파일 간 동기화는 적절한 수단(DBWR, Checkpoint)을 이용해 나중에 배치(Batch) 방식으로 일괄 처리한다.

'Fast Commit' : 사용자의 갱신내용이 메모리상의 버퍼 블록에만 기록된 채 아직 디스크에 기록되지 않았더라도 Redo 로그를 믿고

빠르게 커밋을 완료

  • Online Redo 로그
    캐시에 저장된 변경사항이 아직 데이터 파일에 기록되지 않은 상태에서 정전 등으로 인스턴스가 비정상 종료되면, 그때까지의 작업내용을 모두 잃게 된다. 이러한 트랜잭션 데이터의 유실에 대비하기 위해 Oracle은 Online Redo 로그를 사용한다.
  • '캐시 복구' " 마지막 체크포인트 이후부터 사고 발생 직전까지 수행되었던 트랜잭션들을 Redo 로그를 이용해 재현
  • Online Redo 로그는 최소 두 개 이상의 파일로 구성된다. 현재 사용 중인 파일이 꽉 차면 다음 파일로 로그 스위칭(log switching)이 발생하며, 계속 로그를 써 나가다가 모든 파일이 꽉 차면 다시 첫 번째 파일부터 재사용하는 라운드 로빈(round-robin) 방식을 사용
  • 트랜잭션 로그
    트랜잭션 로그는 Oracle의 Online Redo 로그와 대응되는 SQL Server의 로그 파일이다. 주 데이터 파일마다, 즉 데이터베이스마다 트랜잭션 로그 파일이 하나씩 생기며, 확장자는 ldf이다. 트랜잭션 로그 파일은 내부적으로 '가상 로그 파일'이라 불리는 더 작은 단위의 세그먼트로 나뉘며, 이 가상 로그 파일의 개수가 너무 많아지지 않도록(즉, 조각화가 발생하지 않도록) 옵션을 지정하는 게 좋다. 예를 들어, 로그 파일을 애초에 넉넉한 크기로 만들어 자동 증가가 발생하지 않도록 하거나, 어쩔 수 없이 자동 증가한다면 증가하는 단위를 크게 지정하는 것이다.
  • Archived(=Offline) Redo 로그
    Archived Redo 로그는 Oracle에서 Online Redo 로그가 재사용되기 전에 다른 위치로 백업해 둔 파일을 말한다. 디스크가 깨지는 등 물리적인 저장 매체에 문제가 생겼을 때 데이터베이스(또는 미디어) 복구를 위해 사용된다. 참고로, SQL Server에는 Archived Redo 로그에 대응되는 개념이 없다.

4. 메모리 구조

메모리 구조는 시스템 공유 메모리 영역과 프로세스 전용 메모리 영역으로 구분된다.

  • 시스템 공유 메모리 영역
    시스템 공유 메모리는 말 그대로 여러 프로세스(또는 쓰레드)가 동시에 액세스할 수 있는 메모리 영역.
  • Oracle에선 'System Global Area(SGA)', SQL Server에선 'Memory Pool'이라고 부른다
  • DB 버퍼 캐시, 공유 풀, 로그 버퍼가 있다.
  • 공유 메모리 영역은 그 외에 Large 풀(Large Pool), 자바 풀(Java Pool)
  • 시스템 구조와 제어 구조를 캐싱하는 영역도 포함. 시스템 공유 메모리 영역은 여러 프로세스에 공유되기 때문에 내부적으로 래치(Latch), 버퍼 Lock, 라이브러리 캐시 Lock/Pin 같은 액세스 직렬화 메커니즘이 사용
  • 프로세스 전용 메모리 영역
    서버 프로세스가 자신만의 전용 메모리 영역 'Process Global Area(PGA)'라고 부르며, 데이터를 정렬하고 세션과 커서에 관한 상태 정보를 저장하는 용도로 사용.
  • 쓰레드(Thread) 기반 아키텍처를 사용하는 SQL Server는 프로세스 전용 메모리 영역을 갖지 않는다. 쓰레드는 전용 메모리 영역을 가질 수 없고, 부모 프로세스의 메모리 영역을 사용하기 때문이다.

가. DB 버퍼 캐시(DB Buffer Cache)

DB 버퍼 캐시는 데이터 파일로부터 읽어 들인 데이터 블록을 담는 캐시 영역이다.

인스턴스에 접속한 모든 사용자 프로세스는 서버 프로세스를 통해 DB 버퍼 캐시의 버퍼 블록을 동시에(내부적으로는 버퍼 Lock을 통해 직렬화) 액세스할 수 있음.

일부 Direct Path Read 메커니즘이 작동하는 경우를 제외하면, 모든 블록 읽기는 버퍼 캐시를 통해 이루어진다. 즉, 읽고자 하는 블록을 먼저 버퍼 캐시에서 찾아보고 없을 때 디스크에서 읽는다. 디스크에서 읽을 때도 먼저 버퍼 캐시에 적재한 후에 읽는다.

데이터 변경도 버퍼 캐시에 적재된 블록을 통해 이루어지며, 변경된 블록(Dirty 버퍼 블록)을 주기적으로 데이터 파일에 기록하는 작업은 DBWR 프로세스의 몫이다. 디스크 I/O는 물리적으로 액세스 암(Arm)이 움직이면서 헤드를 통해 이루어지는 반면, 메모리 I/O는 전기적 신호에 불과하기 때문에 디스크 I/O에 비교할 수 없을 정도로 빠르다. 디스크에서 읽은 데이터 블록을 메모리 상에 보관해 두는 기능이 모든 데이터베이스 시스템에 필수적인 이유다.

 

1) 버퍼 블록의 상태

모든 버퍼 블록은 아래 세 가지 중 하나의 상태에 놓인다.

  • Free 버퍼 : 인스턴스 기동 후 아직 데이터가 읽히지 않아 비어 있는 상태(Clean 버퍼)이거나, 데이터가 담겼지만 데이터 파일과 서로 동기화돼 있는 상태여서 언제든지 덮어 써도 무방한 버퍼 블록을 말한다. 데이터 파일로부터 새로운 데이터 블록을 로딩하려면 먼저 Free 버퍼를 확보해야 한다. Free 상태인 버퍼에 변경이 발생하면 그 순간 Dirty 버퍼로 상태가 바뀐다.
  • Dirty 버퍼 : 버퍼에 캐시된 이후 변경이 발생했지만, 아직 디스크에 기록되지 않아 데이터 파일 블록과 동기화가 필요한 버퍼 블록을 말한다. 이 버퍼 블록들이 다른 데이터 블록을 위해 재사용되려면 디스크에 먼저 기록되어야 하며, 디스크에 기록되는 순간 Free 버퍼로 상태가 바뀐다.
  • Pinned 버퍼 : 읽기 또는 쓰기 작업이 현재 진행 중인 버퍼 블록을 말한다.

2) LRU 알고리즘

버퍼 캐시는 유한한 자원이므로 모든 데이터를 캐싱해 둘 수 없다. 따라서 모든 DBMS는 사용빈도가 높은 데이터 블록 위주로 버퍼 캐시가 구성되도록 LRU(least recently used) 알고리즘을 사용한다. 모든 버퍼 블록 헤더를 LRU 체인에 연결해 사용빈도 순으로 위치를 옮겨가다가, Free 버퍼가 필요해질 때면 액세스 빈도가 낮은 쪽(LRU end) 데이터 블록부터 밀어내는 방식이다.

나. 공유 풀(Shared Pool)

공유 풀은 딕셔너리 캐시와 라이브러리 캐시로 구성되며, 버퍼 캐시처럼 LRU 알고리즘을 사용한다. SQL Server에서 같은 역할을 하는 메모리 영역을 '프로시저 캐시(Procedure Cache)'라고 부른다.

  • 딕셔너리 캐시
    데이터베이스 딕셔너리(Dictionary)는 테이블, 인덱스 같은 오브젝트는 물론 테이블 스페이스, 데이터 파일, 세그먼트, 익스텐트, 사용자, 제약에 관한 메타 정보를 저장하는 곳.
  • 라이브러리 캐시
    라이브러리 캐시(Library Cache)는 사용자가 수행한 SQL문과 실행계획, 저장 프로시저를 저장해 두는 캐시영역.

 

실행계획(execution plan) : 사용자가 SQL 명령어를 통해 결과집합을 요청하면 이를 최적으로(→가장 적은 리소스를 사용하면서 가장 빠르게) 수행하기 위한 처리 루틴을 생성

 

하드 파싱(Hard Parsing) :쿼리 구문을 분석해서 문법 오류 및 실행 권한 등을 체크하고, 최적화(Optimization) 과정을 거쳐 실행계

획을 만들고, SQL 실행엔진이 이해할 수 있는 형태로 포맷팅하는 전 과정.

(특히 최적화 과정은 하드 파싱을 무겁게 만드는 가장 결정적 요인)

다. 로그 버퍼(Log Buffer)

로그 엔트리도 파일에 곧바로 기록하는 것이 아니라 먼저 로그 버퍼에 기록한다.

(건건이 디스크에 기록하기보다 일정량을 모았다가 기록하면 훨씬 빠르기 때문)

서버 프로세스가 데이터 블록 버퍼에 변경을 가하기 전에 Redo 로그 버퍼에 먼저 기록해 두면 주기적으로 LGWR 프로세스가 Redo 로그 파일에 기록한다.

(Oracle의 Redo 로그, Redo 로그 버퍼와 대비되는 개념이 SQL Server의 트랜잭션 로그, 로그 캐시)

변경이 가해진 Dirty 버퍼를 데이터 파일에 기록하기 전에 항상 로그 버퍼를 먼저 로그 파일에 기록해야만 하는데, 그 이유는 인스턴스 장애가 발생할 때면 로그 파일에 기록된 내용을 재현해 캐시 블록을 복구하고, 최종적으로 커밋되지 않은 트랜잭션은 롤백해야 한다.

이때, 로그 파일에는 없는 변경내역이 이미 데이터 파일에 기록돼 있으면 사용자가 최종 커밋하지 않은 트랜잭션이 커밋되는 결과를 초래하기 때문.

정리 : 버퍼 캐시 블록을 갱신하기 전에 변경사항을 먼저 로그 버퍼에 기록해야 하며, Dirty 버퍼를 디스크에 기록하기 전에 해당 로그 엔트리를 먼저 로그 파일에 기록해야 하는데, 이를 'Write Ahead Logging'이라고 한다.

로그 파일에 기록했음이 보장돼야 안심하고 커밋을 완료할 수 있다.

라. PGA(Process Global Area)

PGA는 다른 프로세스와 공유되지 않는 독립적인 메모리 공간으로서, 래치 메커니즘이 필요 없어 똑같은 개수의 블록을 읽더라도 SGA 버퍼 캐시에서 읽는 것보다 훨씬 빠르다.

  • User Global Area(UGA)
  • 각 세션을 위한 독립적인 메모리 공간이 필요해지는데, 이를 'UGA(User Global Area)'라고함
  • 전용서버 : 프로세스와 세션이 1:1관계(PGA에 할당)
  • 공유서버 : 프로세스와 세션이 1:M관계(SGA 라지풀설정지 라지풀 또는 Shared pool에 할당)
  • Call Global Area(CGA)
    PGA에 할당되는 메모리 공간으로는 CGA도 있다. Oracle은 하나의 데이터베이스 Call을 넘어서 다음 Call까지 계속 참조되어야 하는 정보는 UGA에 담고, Call이 진행되는 동안에만 필요한 데이터는 CGA에 담는다.
  • CGA는 Parse Call, Execute Call, Fetch Call마다 매번 할당받는다. Call이 진행되는 동안 Recursive Call이 발생하면 그 안에서도 Parse, Execute, Fetch 단계별로 CGA가 추가로 할당된다. CGA에 할당된 공간은 하나의 Call이 끝나자마자 해제돼 PGA로 반환된다.
  • Sort Area
    데이터 정렬을 위해 사용되는 영역.
  • 소트 오퍼레이션이 진행되는 동안 공간이 부족해질 때마다 청크(Chunk) 단위로 조금씩 할당.
  • 세션마다 사용할 수 있는 최대 크기를 예전에는 sort_area_size 파라미터로 설정하였으나, 9i부터는 새로 생긴 workarea_size_policy 파라미터를 auto(기본 값)로 설정하면 Oracle이 내부적으로 결정.

PGA 내에서 Sort Area가 할당되는 위치는 SQL문 종류와 소트 수행 단계에 따라 다르다.

DML 문장은 하나의 Execute Call 내에서 모든 데이터 처리를 완료하므로 Sort Area가 CGA에 할당된다.

SELECT 문장의 경우, 수행 중간 단계에 필요한 Sort Area는 CGA에 할당되고, 최종 결과집합을 출력하기 직전 단계에 필요한 Sort Area는 UGA에 할당된다.

쓰레드(Thread) 기반 아키텍처를 사용하는 SQL Server는 프로세스 전용 메모리 영역을 갖지 않는다. 대신, 데이터 정렬은 Memory Pool 안에 있는 버퍼 캐시에서 수행하며, 세션 관련 정보는 Memory Pool 안에 있는 Connection Context 영역에 저장한다.

5. 대기 이벤트

DBMS 내부에서 활동하는 수많은 프로세스 간에는 상호작용이 필요하며, 그 과정에서 다른 프로세스가 일을 마칠 때까지 기다려야만 하는 상황이 자주 발생.

그때마다 해당 프로세스는 자신이 일을 계속 진행할 수 있는 조건이 충족될 때까지 수면(sleep) 상태로 대기하는데, 그 기간에 정해진 간격으로(1초, 3초 등) 각 대기 유형별 상태와 시간 정보가 공유 메모리 영역에 저장.

대개 누적치만 저장되지만, 사용자가 원하면(10046 이벤트 트레이스를 활성화하면) 로그처럼 파일로 기록해 주기도 한다.

이러한 대기 정보를 Oracle에서는 '대기 이벤트(Wait Event)'라고 부르며, SQL Server에서는 '대기 유형(Wait Type)'이라고 부른다.

세션 또는 시스템 전체에 발생하는 병목 현상과 그 원인을 찾아 문제를 해결하는 방법과 과정을 다루는 이 방법론은, 데이터베이스 서버의 응답 시간을 서비스 시간과 대기 시간의 합으로 정의하고 있다.

Response Time = Service Time + Wait Time
= CPU Time + Queue Time

서비스 시간(Service Time) : 프로세스가 정상적으로 동작하며 일을 수행한 시간(CPU Time)

대기 시간(Wait Time) : 프로세스가 잠시 수행을 멈추고 대기한 시간. ('Queue Time')

Response Time Analysis 방법론은 Response Time을 위와 같이 정의하고, CPU Time과 Wait Time을 각각 break down 하면서 서버의 일량과 대기 시간을 분석해 나간다.

CPU Time은 파싱 작업에 소비한 시간인지 아니면 쿼리 본연의 오퍼레이션 수행을 위해 소비한 시간인지를 분석.

Wait Time은 각각 발생한 대기 이벤트들을 분석해 가장 시간을 많이 소비한 이벤트 중심으로 해결방안을 모색.

Oracle 10g 기준으로 대기 이벤트 개수는 890여 개

 

가. 라이브러리 캐시 부하

아래는 라이브러리 캐시에서 SQL 커서를 찾고 최적화하는 과정에 경합이 발생했음을 나타나는 대기 이벤트다.

  • latch: shared pool
  • latch: library cache

라이브러리 캐시와 관련해 자주 발생하는 대기 이벤트로는 아래 2가지가 있는데, 이들은 수행 중인 SQL이 참조하는 오브젝트에 다른 사용자가 DDL 문장을 수행할 때 나타난다.

  • library cache lock
  • library cache pin

나. 데이터베이스 Call과 네트워크 부하

아래 이벤트에 의해 소모된 시간은 애플리케이션과 네트워크 구간에서 소모된 시간으로 이해하면 된다.

  • SQL*Net message from client
  • SQL*Net message to client
  • SQL*Net more data to client
  • SQL*Net more data from client

SQL*Net message from client 이벤트는 사실 데이터베이스 경합과는 관련이 없다.

클라이언트로부터 다음 명령이 올 때까지 Idle 상태로 기다릴 때 발생하기 때문이다

나머지 세 개의 대기 이벤트는 실제 네트워크 부하가 원인일 수 있다. SQL*Net message to client와 SQL*Net more data to client 이벤트는 클라이언트에게 메시지를 보냈는데 메시지를 잘 받았다는 신호가 정해진 시간보다 늦게 도착하는 경우에 나타나며, 클라이언트가 너무 바쁜 경우일 수도 있다. SQL*Net more data from client 이벤트는 클라이언트로부터 더 받을 데이터가 있는데 지연이 발생하는 경우다.

다. 디스크 I/O 부하

아래는 모두 디스크 I/O가 발생할 때마다 나타나는 대기 이벤트이다.

  • db file sequential read (single Block I/O 수행시)
  • db file scattered read (Multiblock I/O 수행시)
  • direct path read
  • direct path write
  • direct path write temp
  • direct path read temp
  • db file parallel read

Single Block I/O : 한번의 I/O Call에 하나의 데이터 블록만 읽는 것을 말한다. 인덱스 블록을 읽을 때, 그리고 인덱스를 거쳐 테이블

블록을 액세스할 때 이 방식을 사용.

Multiblock I/O : I/O Call이 필요한 시점에 인접한 블록들을 같이 읽어 메모리에 적재하는 것.

Table Full Scan 또는 Index Fast Full Scan 시 나타난다.

라. 버퍼 캐시 경합

아래는 버퍼 캐시에서 블록을 읽는 과정에 경합이 발생했음을 나타나는 대기 이벤트이다.

  • latch: cache buffers chains
  • latch: cache buffers lru chain
  • buffer busy waits
  • dfree buffer waits

버퍼 캐시에서 블록을 읽더라도 이들 대기 이벤트가 심하게 발생하는 순간 동시성은 현저히 저하되는데, 이들 대기 이벤트를 해소하는 방안도 디스크 I/O 부하 해소 방안과 다르지 않다. 따라서 이들 경합의 해소 원리도 4절과 더불어 4장, 5장에서 함께 다루게 된다.

마. Lock 관련 대기 이벤트

아래 'enq'로 시작되는 대기 이벤트는 Lock과 관련된 것으로서, 그 발생 원인과 해소 방안을 2장에서 일부 소개한다.

  • enq: TM - contention
  • enq: TX - row lock contention
  • enq: TX - index contention
  • enq: TX - allocate ITL entry
  • enq: TX contention
  • latch free

latch free는 특정 자원에 대한 래치를 여러 차례(2,000번 가량) 요청했지만 해당 자원이 계속 사용 중이어서 잠시 대기 상태로 빠질 때마다 발생하는 대기 이벤트다.

Lock : 사용자 데이터를 보호하

래치 : SGA에 공유돼 있는 갖가지 자료구조를 보호할 목적으로 사용하는 가벼운 Lock.

래치도 일종의 Lock이지만, 큐잉(Queueing) 메커니즘을 사용하지 않는다. 따라서 특정 자원에 액세스하려는 프로세스는 래치 획득에 성공할 때까지 시도를 반복할 뿐, 우선권을 부여 받지는 못한다. 이는 가장 먼저 래치를 요구했던 프로세스가 가장 늦게 래치를 얻을 수도 있음을 뜻한다.

지금까지 소개한 것 외에 자주 발생하는 대기 이벤트로는 아래와 같은 것들이 있다.

  • log file sync
  • checkpoint completed
  • log file switch completion
  • log buffer space
Posted by redkite
, |

한개의 Oracle Database 내에 취급가능한 데이터 파일의 최대갯수는 64000개 라는군요.

그리고 한개의 tablespace (small tablespace) 가 가질수 있는 파일의 갯수는 1022개 라고 하네요.

(11gR2 기준)

 

SQL> -- 현재 오라클에게 셋팅되어 있는 테이블스페이스 타입

col property_value for a32

select PROPERTY_NAME, PROPERTY_VALUE

from DATABASE_PROPERTIES

where PROPERTY_NAME = 'DEFAULT_TBS_TYPE';

 

SQL> -- 디폴트 테이블스페이스를 변경 [BIGFILE]

alter database set default BIGFILE tablespace;

SQL> -- 디폴트 테이블스페이스를 변경 [SMALLFILE]

alter database set default SMALLFILE tablespace;

Posted by redkite
, |

JDBC Version JDK Driver File Name

------------ ---- ----------------

11.2.0 1.6.x ojdbc6.jar

1.5.x ojdbc5.jar

11.1.0 1.6.x ojdbc6.jar

1.5.x ojdbc5.jar

10.2.0 1.5.x ojdbc14.jar

1.4.x ojdbc14.jar

1.3.x classes12.jar

1.2.x classes12.jar

10.1.0 1.4.x ojdbc14.jar

1.3.x classes12.jar

1.2.x classes12.jar

9.2.0 1.4.x ojdbc14.jar

1.3.x classes12.zip

1.2.x classes12.zip

1.1.x classes111.zip

Posted by redkite
, |

Oracle 11g RAC Basic Commands (운영 기본 명령어)

#####################################################################################
-- Listener (stop, start, status)
-- srvctl stop listener -n <hostname> -l LISTENER
#####################################################################################

srvctl stop listener -n rac1 //

-l LISTENER
srvctl start listener -n rac1 -l LISTENER
srvctl status listener -n rac1 -l LISTENER

srvctl stop listener -n rac2 -l LISTENER
srvctl start listener -n rac2 -l LISTENER
srvctl status listener -n rac2 -l LISTENER


#####################################################################################
-- Oracle instance and service (status)
-- srvctl status database -d <database_name>
#####################################################################################

srvctl status database -d CRMDB


#####################################################################################
-- Oracle 11g RAC stop commands
-- srvctl stop instance -d <database_name> -i CRMDB1<instance_name>
-- srvctl stop listener -n r<hostname> -l LISTENER
-- srvctl stop nodeapps -n <hostname>
#####################################################################################

--RAC1

emctl stop dbconsole

srvctl stop instance -d CRMDB -i CRMDB1
srvctl status instance -d CRMDB -i CRMDB1

srvctl stop listener -n rac1 -l LISTENER
srvctl status listener -n rac1 -l LISTENER

srvctl stop nodeapps -n rac1

--RAC2

emctl stop dbconsole

srvctl stop instance -d CRMDB -i CRMDB2
srvctl status instance -d CRMDB -i CRMDB1

srvctl stop listener -n rac2 -l LISTENER
srvctl status listener -n rac2 -l LISTENER

srvctl stop nodeapps -n rac2





#####################################################################################
-- Oracle 11g RAC start commands
-- srvctl start listener -n r<hostname> -l LISTENER
-- srvctl start instance -d <database_name> -i <instance_name>

#####################################################################################

--RAC1

srvctl start nodeapps -n rac1
srvctl status nodeapps -n rac1

srvctl start listener -n rac1 -l LISTENER
srvctl status listener -n rac1 -l LISTENER

srvctl start instance -d CRMDB -i CRMDB1
srvctl status instance -d CRMDB -i CRMDB1

emctl start dbconsole



--RAC2

srvctl start nodeapps -n rac2
srvctl status nodeapps -n rac2

srvctl start listener -n rac2 -l LISTENER
srvctl status listener -n rac2 -l LISTENER

srvctl start instance -d CRMDB -i CRMDB2
srvctl status instance -d CRMDB -i CRMDB2

emctl start dbconsole

#####################################################################################
-- All Database (stop, start)
-- srvctl start database -d <database name>
#####################################################################################

srvctl start database -d CRMDB
srvctl stop database -d CRMDB

Posted by redkite
, |

0011. ROWNUM 쿼리 분석

ROWNUM의 동작 원리와 활용 방법 SQL*Plus 명령

결과 셋의 제한

ROWNUM은 오라클 데이터베이스가 제공하는 마술과도 같은 컬럼입니다. 이 때문에 많은 사용자들이 문제를 겪기도 합니다. 하지만 그 원리와 활용 방법을 이해한다면 매우 유용하게 사용할 수 있습니다. 필자는 주로 두 가지 목적으로 ROWNUM을 사용합니다.

  • Top-N 프로세싱: 이 기능은 다른 일부 데이터베이스가 제공하는 LIMIT 구문과 유사합니다.
  • 쿼리 내에서의 페이지네이션(pagination) – 특히 웹과 같은 "stateless" 환경에서 자주 활용됩니다. 필자는 asktom.oracle.com 웹 사이트에서도 이 테크닉을 사용하고 있습니다.

두 가지 활용 방안을 설명하기 전에, 먼저 ROWNUM의 동작 원리에 대해 살펴 보기로 하겠습니다


ROWNUM의 동작 원리

ROWNUM은 쿼리 내에서 사용 가능한 (실제 컬럼이 아닌) 가상 컬럼(pseudocolumn)입니다. ROWNUM에는 숫자 1, 2, 3, 4, ... N의 값이 할당됩니다. 여기서 N 은 ROWNUM과 함께 사용하는 레코드(row, record)의 수를 의미합니다. ROWNUM의 값은 레코드에 영구적으로 할당되지 않습니다(이는 사람들이 많이 오해하는 부분이기도 합니다). 테이블의 레코드는 숫자와 연계되어 참조될 수 없습니다. 따라서 테이블에서 "row 5"를 요청할 수 있는 방법은 없습니다. "row 5"라는 것은 존재하지 않기 때문입니다.

또 ROWNUM 값이 실제로 할당되는 방법에 대해서도 많은 사람들이 오해를 하고 있습니다. ROWNUM 값은 쿼리의 조건절이 처리되고 난 이후, 그리고 sort, aggregation이 수행되기 이전에 할당됩니다. 또 ROWNUM 값은 할당된 이후에만 증가(increment) 됩니다. 따라서 아래 쿼리는 로우를 반환하지 않습니다.

select * from t where ROWNUM > 1;

첫 번째 로우에 대해 ROWNUM > 1의 조건이 True가 아니기 때문에, ROWNUM은 2로 증가하지 않습니다.
아래와 같은 쿼리를 생각해 봅시다.

select ..., ROWNUM from t where <where clause> group by <columns>having <having clause> order by <columns>;

이 쿼리는 다음과 같은 순서로 처리됩니다.

1. FROM/WHERE 절이 먼저 처리됩니다.
2. ROWNUM이 할당되고 FROM/WHERE 절에서 전달되는 각각의 출력 레코드에 대해 증가(increment) 됩니다.
3. SELECT가 적용됩니다.
4. GROUP BY 조건이 적용됩니다.
5. HAVING이 적용됩니다.
6. ORDER BY 조건이 적용됩니다.

따라서 아래와 같은 쿼리는 에러가 발생할 수 밖에 없습니다.

select * from emp where ROWNUM <= 5 order by sal desc;

이 쿼리는 가장 높은 연봉을 받는 다섯 명의 직원을 조회하기 위한 Top-N 쿼리로 작성되었습니다.
하지만 실제로 쿼리는 5 개의 레코드를 랜덤하게(조회되는 순서대로) 반환하고 salary를 기준으로 정렬합니다.
이 쿼리를 위해서 사용되는 가상코드(pseudocode)가 아래와 같습니다.

ROWNUM = 1for x in ( select * from emp )loop exit when NOT(ROWNUM <= 5) OUTPUT record to temp ROWNUM = ROWNUM+1end loopSORT TEMP

위에서 볼 수 있듯 처음의 5 개 레코드를 가져 온후 바로 sorting이 수행됩니다.
쿼리에서 "WHERE ROWNUM = 5" 또는 "WHERE ROWNUM > 5"와 같은 조건은 의미가 없습니다.
이는 ROWNUM 값이 조건자(predicate) 실행 과정에서 레코드에 할당되며, 레코드가 WHERE 조건에 의해 처리된 이후에만 increment 되기 때문입니다.

올바르게 작성된 쿼리가 아래와 같습니다.

select * from ( select * from emp order by sal desc ) where ROWNUM <= 5;

위 쿼리는 salary를 기준으로 EMP를 내림차순으로 정렬한 후, 상위의 5 개 레코드(Top-5 레코드)를 반환합니다.
아래에서 다시 설명되겠지만, 오라클 데이터베이스가 실제로 전체 결과 셋을 정렬하지 않습니다.
(오라클 데이터베이스는 좀 더 지능적인 방식으로 동작합니다.) 하지만 사용자가 얻는 결과는 동일합니다.


ROWNUM을 이용한 Top-N 쿼리 프로세싱

일반적으로 Top-N 쿼리를 실행하는 사용자는 다소 복잡한 쿼리를 실행하고, 그 결과를 정렬한 뒤 상위의 N 개 로우만을 반환하는 방식을 사용합니다. ROWNUM은 Top- N쿼리를 위해 최적화된 기능을 제공합니다. ROWNUM을 사용하면 대량의 결과 셋을 정렬하는 번거로운 과정을 피할 수 있습니다. 먼저 그 개념을 살펴보고 예제를 통해 설명하기로 하겠습니다.

아래와 같은 쿼리가 있다고 가정해 봅시다.

select ... from ... where ... order by columns;

또 이 쿼리가 반환하는 데이터가 수천 개, 수십만 개, 또는 그 이상에 달한다고 가정해 봅시다. 하지만 사용자가 실제로 관심 있는
것은 상위 N개(Top 10, Top 100)의 값입니다. 이 결과를 얻기 위한 방법에는 두 가지가 있습니다.

  • 클라이언트 애플리케이션에서 쿼리를 실행하고 상위 N 개의 로우만을 가져오도록 명령
  • 쿼리를 인라인 뷰(inline view)로 활용하고, ROWNUM을 이용하여 결과 셋을 제한 (예: SELECT * FROM (your_query_here) WHERE ROWNUM <= N)

두 번째 접근법은 첫 번째에 비해 월등한 장점을 제공합니다. 그 이유는 두 가지입니다. 첫 번째로, ROWNUM을 사용하면 클라이언트의 부담이 줄어듭니다. 데이터베이스에서 제한된 결과 값만을 전송하기 때문입니다. 두 번째로, 데이터베이스에서 최적화된 프로세싱 방법을 이용하여 Top N 로우를 산출할 수 있습니다. Top-N 쿼리를 실행함으로써, 사용자는 데이터베이스에 추가적인 정보를 전달하게 됩니다. 그 정보란 바로 "나는N 개의 로우에만 관심이 있고, 나머지에 대해서는 관심이 없다"는 메시지입니다. 이제, 정렬(sorting) 작업이 데이터베이스 서버에서 어떤 원리로 실행되는지 설명을 듣고 나면 그 의미를 이해하실 수 있을 것입니다. 샘플 쿼리에 위에서 설명한 두 가지 접근법을 적용해 보기로 합시다.

select * from t order by unindexed_column;

여기서 T가 1백만 개 이상의 레코드를 저장한 큰 테이블이라고, 그리고 각각의 레코드가 100 바이트 이상으로 구성되어 있다고
가정해 봅시다. 그리고 UNINDEXED_COLUMN은 인덱스가 적용되지 않은 컬럼이라고, 또 사용자는 상위 10 개의 로우에만 관심이
있다고 가정하겠습니다. 오라클 데이터베이스는 아래와 같은 순서로 쿼리를 처리합니다.

1. T에 대해 풀 테이블 스캔을 실행합니다.
2. UNINDEXED_COLUMN을 기준으로 T를 정렬합니다. 이 작업은 "full sort"로 진행됩니다.
3. Sort 영역의 메모리가 부족한 경우 임시 익스텐트를 디스크에 스왑하는 작업이 수행됩니다.
4. 임시 익스텐트를 병합하여 상위 10 개의 레코드를 확인합니다.
5.쿼리가 종료되면 임시 익스텐트에 대한 클린업 작업을 수행합니다. .

결과적으로 매우 많은 I/O 작업이 발생합니다. 오라클 데이터베이스가 상위 10 개의 로우를 얻기 위해 전체 테이블을 TEMP 영역으로 복사했을 가능성이 높습니다.

그럼 다음으로, Top-N 쿼리를 오라클 데이터베이스가 개념적으로 어떻게 처리할 수 있는지 살펴 보기로 합시다.

select * from (select * from t order by unindexed_column) where ROWNUM < :N;

오라클 데이터베이스가 위 쿼리를 처리하는 방법은 아래와 같습니다.

1. 앞에서와 마찬가지로 T에 대해 풀-테이블 스캔을 수행합니다(이 과정은 피할 수 없습니다).
2. :N 엘리먼트의 배열(이 배열은 메모리에 저장되어 있을 가능성이 높습니다)에서 :N개의 레코드만을 정렬합니다.

상위N 개의 레코드는 이 배열에 정렬된 순서로 입력됩니다. N +1 레코드를 가져온 경우, 이 레코드를 배열의 마지막 레코드와 비교합니다. 이 레코드가 배열의 N +1 슬롯에 들어가야 하는 것으로 판명되는 경우, 레코드는 버려집니다. 그렇지 않은 경우, 레코드를 배열에 추가하여 정렬한 후 기존 레코드 중 하나를 삭제합니다. Sort 영역에는 최대 N 개의 레코드만이 저장되며, 따라서 1 백만 개의 레코드를 정렬하는 대신N 개의 레코드만을 정렬하면 됩니다.

이처럼 간단한 개념(배열의 활용, N개 레코드의 정렬)을 이용하여 성능 및 리소스 활용도 면에서 큰 이익을 볼 수 있습니다. (TEMP 공간을 사용하지 않아도 된다는 것은 차치하더라도) 1 백만 개의 레코드를 정렬하는 것보다 10 개의 레코드를 정렬하는 것이 메모리를 덜 먹는다는 것은 당연합니다.

아래의 테이블 T를 이용하면, 두 가지 접근법이 모두 동일한 결과를 제공하지만 사용되는 리소스는 극적인 차이를 보임을 확인할 수 있습니다.

create table tasselect dbms_random.value(1,1000000) id, rpad('*',40,'*' ) data from dualconnect by level <= 100000;begindbms_stats.gather_table_stats( user, 'T');end;/Now enable tracing, viaexec dbms_monitor.session_trace_enable(waits=>true);

다음으로 ROWNUM과 함께 top-N 질의를 사용해보면:

select * from(select * from t order by id)where rownum <= 10;

마지막으로 상위 10 개의 레코드만을 반환하는 쿼리를 실행합니다.

declarecursor c isselect * from t order by id;l_rec c%rowtype;begin open c; for i in 1 .. 10 loop fetch c into l_rec; exit when c%notfound; end loop; close c;end;/


이 쿼리를 실행한 후, TKPROF를 사용해서 트레이스 결과를 확인할 수 있습니다. 먼저 Top-N 쿼리 수행 후 확인한 트레이스
결과가 Listing 1과 같습니다.

Code Listing 1: ROWNUM을 이용한 Top-N 쿼리

select * from(select * from t order by id)where rownum <= 10call count cpu elapsed disk query current rows-------- -------- ------- ------- ------- -------- -------- ------ Parse 1 0.00 0.00 0 0 0 0Execute 1 0.00 0.00 0 0 0 0Fetch 2 0.04 0.04 0 949 0 10-------- -------- ------- ------- ------- -------- -------- ------ total 4 0.04 0.04 0 949 0 10Rows Row Source Operation----------------- ---------------------------------------------------10 COUNT STOPKEY (cr=949 pr=0 pw=0 time=46997 us)10 VIEW (cr=949 pr=0 pw=0 time=46979 us)10 SORT ORDER BY STOPKEY (cr=949 pr=0 pw=0 time=46961 us)100000 TABLE ACCESS FULL T (cr=949 pr=0 pw=0 time=400066 us)

이 쿼리는 전체 테이블을 읽어 들인 후, SORT ORDER BY STOPKEY 단계를 이용해서 임시 공간에서 사용되는 로우를 10 개로
제한하고 있습니다. 마지막 Row Source Operation 라인을 주목하시기 바랍니다. 쿼리가 949 번의 논리적 I/O를 수행했으며(cr=949), 물리적 읽기/쓰기는 전혀 발생하지 않았고(pr=0, pw=0), 불과 400066 백만 분의 일초 (0.04 초) 밖에 걸리지 않았습니다. 이 결과를 Listing 2의 실행 결과와 비교해 보시기 바랍니다.


Code Listing 2:ROWNUM을 사용하지 않은 쿼리

SELECT * FROM T ORDER BY IDcall count cpu elapsed disk query current rows-------- -------- ------- ------- ------- -------- -------- ------ Parse 1 0.00 0.00 0 0 0 0Execute 2 0.00 0.00 0 0 0 0Fetch 10 0.35 0.40 155 949 6 10-------- -------- ------- ------- ------- -------- -------- ------ total 13 0.36 0.40 155 949 6 10Rows Row Source Operation----------------- ---------------------------------------------------10 SORT ORDER BY (cr=949 pr=155 pw=891 time=401610 us)100000 TABLE ACCESS FULL T (cr=949 pr=0 pw=0 time=400060 us)Elapsed times include waiting for the following events:Event waited on Times------------------------------ ------------direct path write temp 33direct path read temp 5

결과가 완전히 다른 것을 확인하실 수 있습니다. "elapsed/CPU time"이 크게 증가했으며, 마지막 Row Source Operation 라인을
보면 그 이유를 이해할 수 있습니다. 정렬 작업은 디스크 상에서 수행되었으며, 물리적 쓰기(physical write) 작업이 "pw=891"회 발생했습니다. 또 다이렉트 경로를 통한 읽기/쓰기 작업이 발생했습니다. (10 개가 아닌) 100,000 개의 레코드가 디스크 상에서 정렬되었으며, 이로 인해 쿼리의 실행 시간과 런타임 리소스가 급증하였습니다.


ROWNUM을 이용한 페이지네이션

필자가 ROWNUM을 가장 즐겨 사용하는 대상이 바로 페이지네이션(pagination)입니다. 필자는 결과 셋의 로우 N 에서 로우 M까지를 가져오기 위해 ROWNUM을 사용합니다. 쿼리의 일반적인 형식이 아래와 같습니다.

select * from ( select /*+ FIRST_ROWS(n) */ a.*, ROWNUM rnum from ( your_query_goes_here, with order by ) a where ROWNUM <= :MAX_ROW_TO_FETCH ) where rnum >= :MIN_ROW_TO_FETCH;여기서,

  • FIRST_ROWS(N)는 옵티마이저에게 "나는 앞부분의 로우에만 관심이 있고, 그 중 N 개를 최대한 빨리 가져오기를 원한다"는 메시지를 전달하는 의미를 갖습니다.
  • :MAX_ROW_TO_FETCH는 결과 셋에서 가져올 마지막 로우로 설정됩니다. 결과 셋에서 50 번째 – 60 번째 로우만을 가져오려 한다면 이 값은 60이 됩니다.
  • :MIN_ROW_TO_FETCH는 결과 셋에서 가져올 첫 번째 로우로 설정됩니다. 결과 셋에서 50 번째 – 60 번째 로우만을 가져오려 한다면 이 값은 50이 됩니다.

이 시나리오는 웹 브라우저를 통해 접속한 사용자가 검색을 마치고 그 결과를 기다리고 있는 상황을 가정하고 있습니다. 따라서 첫 번째 결과 페이지(그리고 이어서 두 번째, 세 번째 결과 페이지)를 최대한 빨리 반환해야 할 것입니다. 쿼리를 자세히 살펴 보면, (처음의 :MAX_ROW_TO_FETCH 로우를 반환하는) Top-N 쿼리가 사용되고 있으며, 따라서 위에서 설명한 최적화된 기능을 이용할 수 있음을 알 수 있습니다. 또 네트워크를 통해 클라이언트가 관심을 갖는 로우만을 반환하며, 조회 대상이 아닌 로우는 네트워크로 전송되지 않습니다.

페이지네이션 쿼리를 사용할 때 주의할 점이 하나 있습니다. ORDER BY 구문은 유니크한 컬럼을 대상으로 적용되어야 합니다. 유니크하지 않은 컬럼 값을 대상으로 정렬을 수행해야 한다면 ORDER BY 조건에 별도의 조건을 추가해 주어야 합니다. 예를 들어 SALARY를 기준으로 100 개의 레코드를 정렬하는 상황에서 100 개의 레코드가 모두 동일한 SALARY 값을 갖는다면, 로우의 수를 20-25 개로 제한하는 것은 의미가 없을 것입니다. 여러 개의 중복된 ID 값을 갖는 작은 테이블을 예로 들어 설명해 보겠습니다.

SQL> create table t 2 as 3 select mod(level,5) id, trunc(dbms_random.value(1,100)) data 4 from dual 5 connect by level <= 10000;Table created.

ID 컬럼을 정렬한 후 148-150 번째 로우, 그리고 148–151 번째 로우를 쿼리해 보겠습니다.

SQL> select * 2 from 3 (select a.*, rownum rnum 4 from 5 (select id, data 6 from t 7 order by id) a 8 where rownum <= 150 9 ) 10 where rnum >= 148; ID DATA RNUM------- ---------- -----------0 38 1480 64 1490 53 150SQL>SQL> select * 2 from 3 (select a.*, rownum rnum 4 from 5 (select id, data 6 from t 7 order by id) a 8 where rownum <= 151 9 ) 10 where rnum >= 148; ID DATA RNUM------- ---------- -----------0 59 1480 38 1490 64 1500 53 151

로우 148의 경우 DATA=38의 결과가 반환되었습니다. 두 번째 쿼리에서는 DATA=59의 결과가 반환되었습니다. 두 가지 쿼리 모두
올바른 결과를 반환하고 있습니다. 쿼리는 데이터를 ID 기준으로 정렬한 후 앞부분의 147 개 로우를 버린 후 그 다음의 3 개 또는 4 개의 로우를 반환합니다. 하지만 ID에 중복값이 너무 많기 때문에, 쿼리는 항상 동일한 결과를 반환함을 보장할 수 없습니다. 이 문제를 해결하려면 ORDER BY 조건에 유니크한 값을 추가해 주어야 합니다. 위의 경우에는 ROWID를 사용하면 됩니다.

SQL> select * 2 from 3 (select a.*, rownum rnum 4 from 5 (select id, data 6 from t 7 order by id, rowid) a 8 where rownum <= 150 9 ) 10 where rnum >= 148; ID DATA RNUM------- ---------- -----------0 45 1480 99 1490 41 150SQL>SQL> select * 2 from 3 (select a.*, rownum rnum 4 from 5 (select id, data 6 from t 7 order by id, rowid) a 8 where rownum <= 151 9 ) 10 where rnum >= 148; ID DATA RNUM------- ---------- -----------0 45 1480 99 1490 41 1500 45 151

이제 쿼리를 반복 실행해도 동일한 결과를 보장할 수 있게 되었습니다. ROWID는 테이블 내에서 유니크한 값을 가집니다. 따라서
ORDER BY ID 조건과 ORDER BY ROWID 기준을 함께 사용함으로써 사용자가 기대한 순서대로 페이지네이션 쿼리의 결과를 확인할 수 있습니다.

ROWNUM 개념 정리

지금까지 ROWNUM에 관련하여 아래와 같은 개념을 설명하였습니다.

Posted by redkite
, |

0010. 파티션 테이블 생성

http://docs.oracle.com/cd/B19306_01/server.102/b14231/partiti.htm

1. ADD

ex)

ALTER TABLE LG_CV ADD PARTITION PT_0709 VALUES less than ('0710') TABLESPACE ADWS_00_LG;

2. SPLIT ()

ADD 방법 으로 했는데 "ORA-14074: partition bound must collate higher than that of the last partition" 에러가 날 경우

ex)

alter table LG_TS_URL split partition PT_0710 at('0710')
into (partition PT_0709,partition PT_0710) ;

= SPLIT 설명 =

ALTER TABLE &Table_Name
SPLIT PARTITION &분할대상Partition_Name AT ('&SplitValue')
INTO (
PARTITION &하위Partition_Name TABLESPACE &하위파티션TableSpace_Name,
PARTITION &상위Partition_Name TABLESPACE &상위파티션TableSpace_Name
);

- &Table_Name : 변경할 테이블 명
- &분할대상Partition_Name : Partition Key가 'MAXVALUE'인 현재 최상위 Partition 이름
- &SplitValue : 분할 기준이 되는 값
- &하위Partition_Name : 분할될 영역 중 하위 Partition 명 즉, 최상위 Partition 이름
- &하위파티션TableSpace_Name : 분할될 영역 중 하위 Partition이 사용할 TableSpace명
- &상위Partition_Name : 분할될 영역 중 상위 Partition 명 즉, 신규 Partition 이름
- &상위파티션TableSpace_Name : 분할될 영역 중 상위 Partition이 사용할 TableSpace명
※ Partition Split 구문은 해당 Table의 Local Index를 자동으로 생성하나 Local Index의
Partition 명 및 Tablespace도 Table 분할시 지정하였던 이름으로 지정 및 생성되지여.
고로, Rename 및 Tablespace를 변경 해야함다..
※ Partition Split 구문은 사용시 해당 Table의 Global Index(PK)는 사용불가 상태가 되며
Rebuild 작업을 해야함다.

작업이 끝나면 정상적으로 분할되었나 확인하시면 되여..
SELECT *
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'TABLE명'

Posted by redkite
, |

No. 12141


10g-standbyDB생성.pdf


database crash 시 backup받아둔 datafile과 archive file을 모두 restore하고,
recover하는 작업은 경우에 따라 고객의 요구 사항보다 길어지는 경우가 종종
있다.
이런 경우 미리 standy db를 구성하여 standby db에 recovery를 진행해 두고,
piramry db crash시 바로 stadnby db와 연결하면, db down time을 최소화하는데
많은 도움이 된다.

Oracle 8.1부터 이 standby db에 새로운 기능이 추가되어, 이전 version에서,
주기적으로 archive file 적용 및 recover 작업을 수행해야 하는 필요를 덜어
주었다.
단, Automated Standby database Feature는 8i~10g Standard Edition에서는
지원하지 않는다.

이 문서에서 자세한 설정 방법 및 추가된 기능들을 확인한다.

1. 추가된 기능 정리
(1) primary db에서 archive file생성시 standby db에도 자동 전달

(2) standby db에 전달된 archive file이 자동으로 standby db에 적용

(3) standby db activate없이, standy db를 read only mode로 open

2. 구성 절차

(1) standby db가 구성될 system에 oracle을 primary db와 동일한 version으로
install한다.
- OS는 primary db와 동일해야 한다.
- database는 install할 필요없이, software만 install하면 된다.
- datafile, controlfile, redo log file이 생성될 directory를 만들어
둔다.
(가능하면 primary db와 동일한것이 좋다),

(2) primary db의 init.ora를 standby db에 copy한다.
- primary db의 $ORACLE_HOME/dbs/initSID.ora file을 standby db에
copy한다.
- initSID.ora file에 ifile=로 정의된 file이 있다면 그 file도 해당
directory에 copy한다.
- 이러한 initial parameter중 background_dump_dest, user_dump_dest,
core_dump_dest, archive_log_dest 등에 지정된 directory도 standby 쪽,
server에 생성해둔다.

(3) primary db에 multiple archive destination을 위한 parameter지정
다음과 같은 형태로 primary db를 위한 archive parameter외에,
standby db쪽에 자동으로 archive file이 생성되도록 destination을
initSID.ora file에 지정한다.

log_archive_start = true
log_archive_dest_1 = "location=/user/oradata/archive"
log_archive_format = arch%s.arc

log_archive_dest_2 = 'SERVICE=sby OPTIONAL REOPEN=60'
log_archive_dest_state_2 = ENABLE

- 이 예에서 sby라는 것은 primary db의 tnsnames.ora file에 미리
정의되어 있어야 하며, standby db에 대한 description을 가져야 한다.
- REOPEN은 standby db쪽으로 archive가 실패한경우 지정된 초만큼 후에
다시 archive를 시도하라는 의미이다.
- OPTIONAL의 의미는 지정된 archive가 실패하는 경우라도 primary db의
log_archive_dest_1에 지정된 곳에 archive만 성공하면 archive작업을
중단없이 계속 진행하라는 것이다.

(4) standby db의 initSID.ora file 수정

primary db에서 자동으로 전달되어온 archive file이 위치하게 될
destination과 datafile이나 redo log file이 위치할 directory 구조가
primary db와 다른 경우를 대비한 parameter를 다음 예와 같이 설정한다.

standby_archive_dest=/user/oradata/archive

log_archive_start = true
log_archive_dest_1 = "location=/user/oradata/archive"
log_archive_format = arch%S.ARC

db_file_name_convert="PROD","SBY"
log_file_name_convert="PROD","SBY"

- standby_archive_dest는 primary db에서 multiple archive destination을
지정하는 경우 자동으로 생성될 archive file의 위치를 나타낸다.
- standby_archive_dest뒤에는 log_archive_dest와 같은 location=은
적으면 안된다. 적을시엔 자동으로 archive가 전달되지 않고, primary db의
alert.log에 오류가 기록된다.
- 실제 recover시나 이후 open되어 archive가 생성되는 시에는
log_archive_dest 부분이 참조된다.

- db_file_name_conver나 log_file_name_convert의 경우는, primary db와
standby db간에 datafile, redo log file이 위치하는 directory가 다른
경우 directory 이름중 다른 부분을 치환하도록 하는 것이다.

이 경우 primary db는 /user/oradata/PROD directory에 file이 존재하고,
standby db는 /user/oradata/SBY directory에 위치하는 경우에 대한 예이다.

- 만약 datafile이 여러군데 나뉘어져 있어 이런 변경 부분이 더 필요하다면
다음과 같이 할 수 있다.

db_file_name_convert=('/dbs/t1/','/dbs/t1/s_','dbs/t2/','dbs/t2/s_')
- WindowsNT의 경우는 반드시 directory이름을 반드시 대문자로 하여야 한다.

(5) standby db용 controlfile을 생성
다음 문장을 primary db에서 수행한다. 이후 이렇게 생성된 file은
standby db쪽으로 옮겨질 것이다.

SQL> alter database create standby controlfile as
'/user/oradata/temp/control01.ctl';

(5) primary db의 datafile을 backup받아둔다.
db를 shutdown 시켜 cold backup을 받거나, hot backup을 받는다.
tape등에 backup받는 대신 바로 ftp 등으로 standby db disk로
옮겨도 된다.

(6) 위의 (4),(5)에서 만들어진 controlfile과 datafile을 standby db쪽으로
옮긴다.

(7) standby db에서 다음과 같이 수행한다.

os> sqlplus internal
SQL> startup nomount
SQL> alter database mount standby database;
SQL> recover managed standby database;

- 만약 recover managed standby database대신에 그냥
recover standby database하면, ora-279, 280, 289가 발생하면서,
생성된 archive를 manual하게 적용하면 된다.

(8) standby db에서 primary db가 운영중에 test나 다른 목적으로 data를 읽고자
한다면 read only로 open가능

SQL>alter database open read only;

(9) primary db가 crash가 발생하여 standby db를 운영하고자 한다면 다음과 같이
activate시켜야 하며, 이렇게 한 이후로는 이 standby db는 standby 의 속성은
잃게 되며, 이후에 다시 standby db로 구축하려면 다시 (5)번부터 작업을
재수행하여 구축하여야 한다.

SQL>alter database activate standy database;
SQL>shutdown
SQL>startup

- shutdown후 이제는 더 이상 standby db가 아니므로 primary성격의 multiple
archive destination지정 등을 원하는 경우 parameter를 추가하면 된다.

3. managed recover, read only mode open 관리
(1) managed recover
recover managed database를 수행한 창은 계속 새로 전달되온 archive file을
자동으로 recovery를 시켜준다.
이때 필요에 의해 이 자동 recovery를 중단하고자 한다면,
standby에서 다른 session을 연결하여 다음과 같이 수행하면 된다.

SQL>alter database recover managed standby database cancel;

이렇게 하면,
recover managed standby 상태의 창에서,
ora-283, ora-16037 메시지와 함께, managed recovery가 중단되고,
SQL혹은 SVRMGR prompt상태가 된다.

recover managed standby database와 일반, recover standby database는 필요에
따라, 선택하여 사용하면 되며, recover managed standby databse의 경우 이
문장을 실행한 이후에 생성된 archive file만을 자동 recovery한다.
즉, recover managed standby database문장 수행전에 미리 전달되어 온 archive
file이 있다면, 일단 먼저 recover standby database문장을 통해 recovery를
수행한 이후에, recovey managed standby database문장을 수행하여야 한다.

(2) read only mode open

standby db를 standby db 속성은 그대로 유지하면서 dml 외에 data나 dictionary
조회가 필요한 상황에서는
alter database open read only문장을 수행하여 read only mode로 open할 수 있다.

이렇게 조회후에, 다른 작업없이 recover 문장을 수행하면 다시 mount상태가 되는
것이며, 필요하면 다시 open read only를 하여야 한다.

standby db는 운영 중에 shutdown가 mount, open을 마음대로 할 수 있으나
그 때마다 반드시,
startup nomount;
alter database mount standby database;
(필요한 경우 alter database open read only)
문장을 통해 mount나 open 상태가 되도록 하여야 한다.


Reference Documents
-------------------

<Note:74185.1> Standby Database and Oracle 8.1
<Note:70233.1> How to Create a Oracle 8i Standby Database

Posted by redkite
, |

Version 11.1

 

General Information

Dependencies

file$

ts$

x$ktfbhc

dba_data_files

dba_temp_files

 

dba_free_space

gv$dbfile

 
 

Alter Data Files


Resize An Existing Datafile

ALTER DATABASE DATAFILE '<data_file_name | data_file_number>'
RESIZE <n> K|M|G|T|P|E;

Beware that you can only decrease the size of the datafile with the space that is free between highest used block of the datafile and the last block of the file. If the tablespace is fragmented, the free spaces between extents cannot be deallocated this way. Check dba_free_space for details.

ALTER DATABASE DATAFILE 'c:\oracle\oradata\orabase ools02.tom'
RESIZE 50M;

ALTER DATABASE DATAFILE 'c:\oracle\oradata\orabase ools03.dan'
RESIZE 50M;


Add A Datafile To An Existing Tablespace

ALTER TABLESPACE <tablespace_name>
ADD DATAFILE '<path_and_file_name>' SIZE <n>K|M|G|T|P|E;

ALTER TABLESPACE tools
ADD DATAFILE 'c:\oracle\oradata\orabase ools02.tom' SIZE 20M;

ALTER DATABASE
CREATE DATAFILE '<path_and_file_name>' SIZE <n>K|M|G|T|P|E
AS '<tablespace_name>';

ALTER DATABASE
CREATE DATAFILE 'c:\oracle\oradata\orabase\uwdata03.dbf' SIZE 1G
AS 'UWDATA';


Move Tablespace Datafile

Can also be used to move SYSTEM, SYSAUX, and TEMP tablespace files

SHUTDOWN

STARTUP MOUNT

-- Copy the datafile to it's new location

ALTER DATABASE RENAME FILE
'<old_full_path>' TO '<new_full_path>';

-- then

ALTER DATABASE OPEN;

-- then you can safely delete the old datafile.

conn / as sysdba

shutdown immediate;

startup mount

host

$ cp /u01/oradata/tools01.dbf /u06/oradata/tools01.dbf

$ exit

alter database rename file '/u01/oradata/tools01.dbf'
to '/u06/oradata/tools01.dbf';

alter database open

host

$ rm /u01/oradata/tools.01.dbf

$ exit


Autoextend

ALTER DATABASE DATAFILE <'data_file_name' | data_file_number>
AUTOEXTEND <OFF | ON [NEXT SIZE <n>K|M|G|T|P|E
MAXSIZE <UNLIMITED | <n>K|M|G|T|P|E>;

ALTER DATABASE DATAFILE 'u06/oradata/tools01.dbf' AUTOEXTEND OFF;

ALTER DATABASE DATAFILE 'u06/oradata/tools01.dbf' AUTOEXTEND ON MAXSIZE UNLIMITED;


Online / Offline

ALTER DATABASE DATAFILE <'data_file_name' | data_file_number>
<ONLINE | OFFLINE [FOR DROP]>;

ALTER DATABASE DATAFILE 'u06/oradata/tools01.dbf' OFFLINE;

ALTER DATABASE DATAFILE 'u06/oradata/tools01.dbf' ONLINE;

ALTER DATABASE DATAFILE 'u06/oradata/tools01.dbf' OFFLINE FOR DROP;

 

Alter Temp Files

Resize

alter database tempfile <temp file name>
resize <integer> K|M|G|T|P|E;

ALTER DATABASE TEMPFILE 'temp01.dbf' RESIZE 100M;

Drop

alter database tempfile <temp file name>
drop including datafiles;

ALTER DATABASE TEMPFILE 'temp01.dbf' DROP INCLUDING DATAFILES;

 

Drop Data File


Drop A Datafile

ALTER DATABASE DATAFILE '<file_name_or_file_number>' [offline] DROP;

set linesize 121
col file_name format a80

SELECT file_name, SUM(bytes)/1024/1024 DF_SIZE
FROM dba_data_files
GROUP BY file_name;

ALTER TABLESPACE users ADD datafile SIZE 50M;

SELECT file_name, SUM(bytes)/1024/1024 DF_SIZE
FROM dba_data_files
GROUP BY file_name;

ALTER DATABASE DATAFILE 'C:\ORACLE\PRODUCT\ORADATA\UKOUG\DATAFILE\O1_MF_USERS_35HCKNFO_.DBF'
OFFLINE DROP;

or

ALTER TABLESPACE users DROP DATAFILE 'C:\ORACLE\PRODUCT\ORADATA\UKOUG\DATAFILE\O1_MF_USERS_35HCKNFO_.DBF';

 

Data File Related Queries


Data File Information

set linesize 121
col file_name format a45
col tablespace_name format a20

SELECT file_name, tablespace_name,
bytes/1024/1024 MB, blocks
FROM dba_data_files
UNION ALL
SELECT file_name, tablespace_name,
bytes/1024/1024 MB, blocks
FROM dba_temp_files
ORDER BY tablespace_name, file_name;


Data File Block Sizing

-- as root created a file system with block size 1024

mkfs.ext3 -b 1024 /dev/sda3

-- mounted it

mount /dev/sda3 /mnt/test

-- and issued

iostat -d -t -x /dev/sda3

-- in another shell

dd if=/tmp/foo of=/mnt/test/foo2 bs=1024k

-- the results

Time: 08:47:05
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s
avgrq-sz
avgqu-sz await svctm %util
/dev/sda3 0.00 0.00 2.00 0.00 4.00 0.00 2.00 0.00
2.00
0.10 50.00 50.00 1.00

Time: 08:47:10
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s
avgrq-sz
avgqu-sz await svctm %util
/dev/sda3 0.00 10200.40 0.20 83.60 0.40 20568.00 0.20
10284.00 245.
45 67.92 810.50 31.03 26.00

-- do the math

wsec/s / wrqm/s = 20568.00 / 10200.40 = 2,017

-- Roughly two sectors of 512 bytes. So write were in blocks of 1K.


Uneven Datafile Usage Within A Tablespace

CREATE TABLESPACE bowie_data
DATAFILE 'c:\bowie\bowie_data01.dbf' size 10m,
'c:\bowie\bowie_data02.dbf' size 10m,
'c:\bowie\bowie_data03.dbf' size 10m
uniform size 64;

col segment_name format a30

SELECT file_id, file_name
FROM dba_data_files
WHERE tablespace_name = 'BOWIE_DATA';

CREATE TABLE one (x NUMBER) TABLESPACE bowie_data;
CREATE TABLE two (x NUMBER) TABLESPACE bowie_data;
CREATE TABLE three (x NUMBER) TABLESPACE bowie_data;
CREATE TABLE four (x NUMBER) TABLESPACE bowie_data;

Now we've create 4 tables in this tablespace. Let's see which data file they were placed in ...

SELECT segment_name, file_id
FROM dba_extents
WHERE tablespace_name = 'BOWIE_DATA';

Note that *all* tables have their first extent created in the *first* data file defined to the tablespace.

Now lets grow these tables and see what happens next.


ALTER TABLE one ALLOCATE EXTENT;
ALTER TABLE two ALLOCATE EXTENT;
ALTER TABLE three ALLOCATE EXTENT;
ALTER TABLE four ALLOCATE EXTENT;

SELECT segment_name, file_id
FROM dba_extents
WHERE tablespace_name = 'BOWIE_DATA'
ORDER BY segment_name;

... and the second extent of each table has been created in the second data file of the tablespace.

If a particular table were to keep growing ...


ALTER TABLE four ALLOCATE EXTENT;
ALTER TABLE four ALLOCATE EXTENT;

SELECT segment_name, file_id
FROM dba_extents
WHERE tablespace_name = 'BOWIE_DATA'
ORDER BY segment_name;

You can see how the extents get allocated to the data files in a round robin fashion. But the first extent is allocate to the first data file (providing it has sufficent space) ...

CREATE TABLE five (x NUMBER) TABLESPACE bowie_data;

SELECT segment_name, file_id
FROM dba_extents
WHERE tablespace_name = 'BOWIE_DATA'
ORDER BY segment_name;

Let's add a new data file. What happens now ...

ALTER TABLESPACE bowie_data
ADD DATAFILE 'c:\bowie\bowie_data04.dbf' SIZE 10M;

ALTER TABLE four ALLOCATE EXTENT;

SELECT segment_name, file_id
FROM dba_extents
WHERE tablespace_name = 'BOWIE_DATA'
ORDER BY segment_name;

A new extent is added to table four. And uses the new datafile.

ALTER TABLE four ALLOCATE EXTENT;

SELECT segment_name, file_id
FROM dba_extents
WHERE tablespace_name = 'BOWIE_DATA'
ORDER BY segment_name;

ALTER TABLE four ALLOCATE EXTENT;

SELECT segment_name, file_id
FROM dba_extents
WHERE tablespace_name = 'BOWIE_DATA'
ORDER BY segment_name;

... and now the new file is used. The files are still used in a round robin fashion with the new file slipping in.

Note how file 16 is the *most* used file and file 19 is the least. If I were to allocate several new tables that were only 1 or 2 extents in size, see how file 16 would be the one to be most "filled".

Posted by redkite
, |
  1. B*Tree Index(Balance Tree Index)
    1
    2 -> 1과 root의 중간값 (250) is branch value
    .. 1~250, 251~500 값 사이의 블럭을 leaf라고함
    ...---> 중간의 값(500) is root value
    ....
    .... -> root와 1000의 중간값(750) is branch value
    1000
    ** 잦은 insert, delete로 인해 index 공간 활용도가 떨어질 경우 index rebulid 작업으로 가능하나, index create 시부터 dept가 깊어진 경우는 다른 문제로 해결해야 함.
  2. SELECTIVITY
    select column_name, num_distinct, density from user_tab_col_statistics where table_name = 'EMPLOYEES';
    벨류값이 0.0에 가까울수록 구별할수 있는 값들이 많은것이고 이것을 selectivity가 좋다고 함.
Posted by redkite
, |

최근에 달린 댓글

최근에 받은 트랙백

글 보관함