Oracle 39일차

Table of Contents

[복구 전 준비 사항]

1. 아카이브 로그 모드 확인

> archive log list;

select name, log_mode
from v$database;

2. archive_dest 확인

select *
from v$parameter
where name like '%arch%';

3. flashback off

select name, flashback_on
from v$database;

alter database flashback off;

4. supplemental logging off

select name, supplemental_log_data_min
from v$database;

alter database drop supplemental log data;

5. offline (cold) backup 다시 받아놓기

6. controlfile 생성 스크립트 다운

alter database backup controlfile to trace as '/oracle12/backup/control.sql';

[controlfile 물리적 장애]

mount 단계 진입 불가.
하나의 controlfile이 정상일 경우 cp로 다른 controlfile 생성 후 기동.
모든 controlfile 유실 -> 새로운 controlfile 생성

[실습 – 하나의 controlfile만 손상된 경우]

1. DB shutdown immediate

2. controlfile 하나 삭제

$ rm /home/oracle/oradata/db1/control02.ctl

3. DB startup (error)

$ alert
> startup
ORA-00200:

4. 장애 복구

-- 방법 1) pfile로 DB 기동(장애 난 controlfile 정보 삭제)
-- step1) 새로운 pfile 생성 & DB 종료
> create pfile from spfile;
> shutdown abort

-- step2) pfile 수정 (control02.ctl 정보 삭제)
$ vi initdb1.ora

-- step3) spfile rename 또는 삭제
$ mv spfiledb1.ora spfiledb1.ora.temp

-- step4) startup
정상적으로 올라가면 남아있는 controlfile은 정상이니깐 후속작업을 진행.

-- step5) 정상화(controlfile 2개, spfile 환경)
> shutdown immediate
$ dbs
$ vi initdb1.ora
$ data
$ cp control01.ctl control02.ctl
> startup
> create spfile from pfile;
> shutdown immediate
> startup

-- 방법 2) 애초에 controlfile을 복사해서 만들어놓고 시작.
-- step1) DB 종료 & cp controlfile
> shutdown immediate
$ cp /home/oracle/oradata/db1/control01.ctl /home/oracle/oradata/db1/control02.ctl

-- step2) startup
> startup

[실습 – 하나의 controlfile이 old한 경우]

db는 parameter file에 있는 내용대로 controlfile이 존재하고, 여러 controlfile이 있을 경우 모든 controlfile의 정보가 일치해야 mount 가능.

1. DB shutdonw immediate & control02.ctl을 과거 백업본으로 cp

> shutdown immediate
$ cp /oracle12/backup/cold_backup/control02.ctl /home/oralce/oradata/db1/

2. DB startup (장애 발생)

> startup
ORA-00214: control file '/home/oracle/oradata/db1/control01.ctl' version 3203
inconsistent with file '/home/oracle/oradata/db1/control02.ctl' version 3043

3. 복구 진행

> shutdown abort
$ cp /home/oracle/oradata/db1/control01.ctl /home/oracle/oradata/db1/control02.ctl
> startup

[실습 – 모든 controlfile이 old한 경우]

controlfile끼리의 시점이 일치하면 mount까지는 가능. 하지만 open이 안됨.
controlfile이 datafile, redo log file과 시점이 일치하지 않는다.
datafile들은 미래, controlfile은 과거 시점인 상태.
controlfile 재생성이 가장 깔끔하게 datafile들과 시점 일치하는 복구를 진행할 수 있다.

1. DB shutdown immediate & 백업 디렉터리에서 controlfile 가져오기

> shutdown immediate
$ cp /oracle12/backup/cold_backup/*.ctl /home/oracle/oradata/db1

2. DB startup (error)

startup
ORA-01122: database file 1 failed verification check
ORA-01110: data file 1: '/home/oracle/oradata/db1/system01.dbf'
ORA-01207: file is more recent than control file - old control file

3. controlfile 재생성 스크립트 이용하여 복구

-- controlfile 재생성 스크립트 파일 받는 명령어
alter database backup controlfile to trace as '/oracle12/backup/control.sql';

> shutdown immediate
$ cd /oracle12/backup
$ ss
> startup nomount
> @control_noreset.sql
> alter database open;

4. tempfile 생성

select name from v$tempfile;
-- controlfile 재생성 시 tempfile은 필수가 아니라서 생성해주지 않는다.
-- 이 상태로 운영한다면 대용량 정렬 시 tempfile이 없어서 에러 발생.

alter tablespace temp add tempfile '/home/oracle/oradata/db1/temp01.dbf'
     size 137363456  reuse autoextend on next 655360  maxsize 32767m;

[실습 – 모든 controlfile 유실된 경우]

1. DB 내리고, 모든 controlfile 삭제

> shutdown immediate
$ rm /home/oracle/oradata/db1/*.ctl

2. startup (error)

> startup
ORA-00205: error in identifying control file, check alert log for more info

3. 복구 (바로 위에 적힌 실습과 과정 동일)

(> shutdown abort
> startup nomount)
-- 바로 위에 2번에서 startup 해서 오류나면 nomount상태인 거임. 굳이 abort, startup nomount 할 필요 없음.

> @/oracle12/backup/control_noreset.sql
> alter database open;

-- tempfile
select name from v$tempfile;
alter tablespace temp add tempfile '/home/oracle/oradata/db1/temp01.dbf'
     size 137363456  reuse autoextend on next 655360  maxsize 32767m;

[실습 – 운영 중 controlfile 장애]

DB가 운영 중에 하나 이상의 controlfile 장애 발생하는 경우, DB는 open 상태를 유지하다가 controlfile에 정보를 내려쓸 경우 error 발생 & DB 강제 종료.

현상) shutdown immediate 불가.

해결1) DBWR가 정상 작동한 경우 -> controlfile 재생성 -> open;

해결2) DBWR가 정상 작동하지 않은 경우 -> contorlfile 재성성 -> recover database; -> alter database open;

1. DB open 상태에서 controlfile 삭제

$ rm /home/oracle/oradata/db1/*.ctl

2. shutdown immediate 시도 (error)

> shutdown immediate
ORA-00210: cannot open the specified control file
ORA-00202: control file: '/home/oracle/oradata/db1/control01.ctl'
ORA-27041: unable to open file
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3

3. shutdown abort 시도 & 복구

> shutdown abort
> startup nomount
> @/oracle12/backup/control_noreset.sql

-- recover 가 필요 없을 수도 있는데 소수임.
> recover database;

> alter database

-- temp도 생성
> alter tablespace temp add tempfile '/home/oracle/oradata/db1/temp01.dbf'
     size 137363456  reuse autoextend on next 655360  maxsize 32767m;

[OEL7의 IP고정]

하면 IP가 고정되긴 해서 변경될 일은 없긴 한데, oel7폴더를 옮겨서 리눅스째로 다른 VMware로 옮기는 과정이 더 복잡해진다.

만약 IP가 변했다면 hosts파일, tnsnames.ora 등을 수정해줘야 됨.

** 하는 법
vmware 리눅스창 오른쪽 위에 wired connected -> lan setting -> 톱니바퀴 -> IPv4 method ‘Manual’ -> Addresses 지정(ex. 172.16.124.128 / netmask 255.255.255.0 / gateway 172.16.124.2) -> DNS 설정 (8.8.8.8) -> apply -> 껐다 키기

[redo log member 다중화]

1. 조회

select a.group#,
       a.member,
       b.bytes/1024/1024 as "size(mb)",
       b.archived,
       b.status
from v$logfile a, v$log b
where a.group# = b.group#
order by 1;

2. 멤버 추가

alter database add logfile member
    '/home/oracle/oradata/db1/redo01_2.log' to group 1,
    '/home/oracle/oradata/db1/redo02_2.log' to group 2,
    '/home/oracle/oradata/db1/redo03_2.log' to group 3;

[case1. online 중에 member 하나 물리적 장애]

다중화 구성이 된 경우(member가 2개 이상) 하나의 member가 삭제된 경우 DB는 정상 운영 -> alert log error 발생

해결) online 중에 장애난 멤버를 삭제(controlfile 정보 변경)

1. 현재 redo 상태 조회

select a.group#,
       a.member,
       b.bytes/1024/1024 as "size(mb)",
       b.archived,
       b.status
from v$logfile a, v$log b
where a.group# = b.group#
order by 1;

2. redo 멤버 삭제 (inactive이면서 archive yes인 멤버 하나만 삭제)

-- 강사님과 같은 1번 그룹이 current가 되도록 하는 부분.
alter system switch logfile;

alter system checkpoint;

$ rm /home/oracle/oradata/db1/redo02_2.log

3. 로그스위치(2번 그룹이 current가 되게끔)

alter system switch logfile;
ORA-00313: open failed for members of log group 2 of thread 1
ORA-00312: online log 2 thread 1: '/home/oracle/oradata/db1/redo02_2.log'
ORA-27037: unable to obtain file status
-- alert log에 뜸.

4. controlfile 수정

파일을 cp로 하는 방법은 DB가 online이어서 불가능함.
따라서 controlfile 내용을 현재 파일상태에 맞게 수정해주는 것.

alter database drop logfile member '/home/oracle/oradata/db1/redo02_2.log';
-- current라서 삭제 안됨.
alter system switch logfile;
alter database drop logfile member '/home/oracle/oradata/db1/redo02_2.log';
-- 성공

5. member 재생성

alter database add logfile member '/home/oracle/oradata/db1/redo02_2.log' to group 2;

[case2. redo group 삭제]

그룹이 3개 이상인 경우 그룹의 삭제는 운영 중에 문제가 되지 않는다.(필수 redo group이 2개라서)

상황 설정 :
1) DB online 중에 current가 아닌 그룹을 지우고 다시 복구하는 상황.
2) DB online 중에 current가 아닌 그룹을 지우고 log switch에 의해 삭제된 그룹이 current가 되는 상황.

1) DB online 중에 inactive인(active는 안됨) 그룹을 지우고 다시 복구하는 상황

step1) 현재 리두 상태 조회
select a.group#,
       a.member,
       b.bytes/1024/1024 as "size(mb)",
       b.archived,
       b.status
from v$logfile a, v$log b
where a.group# = b.group#
order by 1;
step2) group 삭제(status가 current가 아니면서 archived가 yes)
alter system switch logfile;
alter system checkpoint;

$ rm /home/oracle/oradata/db1/redo01*
step3) DB shutdown & startup
> shutdown immediate

> startup
ORA-03113: end-of-file on communication channel
Process ID: 3963
Session ID: 19 Serial number: 35949
-- alert log
ORA-27037: unable to obtain file status
ORA-00313: open failed for members of log group 1 of thread
ORA-00312: online log 1 thread 1: '/home/oracle/oradata/db1/redo01.log'
ORA-00312: online log 1 thread 1: '/home/oracle/oradata/db1/redo01_2.log'
step4) 복구

redo file들 상황에 맞춰 controlfile을 수정하는 방법만 가능.
없는 redo file을 옆에 file을 복사해서 만들 수는 없음.

> startup mount
> @~/log.sql
-- 삭제된 redo group이 inactive상태임을 확인 = 삭제 가능

> alter database drop logfile group 1;

> alter database add logfile group 1('/home/oracle/oradata/db1/redo01.log', '/home/oracle/oradata/db1/redo01_2.log') size 200m;

> alter database open;
추가) DB shutdown 안 된(계속 운영 중) 상태에서의 복구
-- inactive인 group 삭제.
$ rm /home/oracle/oradata/db1/redo01*

-- drop & add redo group.
> alter database drop logfile group 1;
> alter database add logfile group 1('/home/oracle/oradata/db1/redo01.log', '/home/oracle/oradata/db1/redo01_2.log') size 200m;

2) DB online 중에 current가 아닌 그룹을 지우고 log switch에 의해 삭제된 그룹이 current가 되는 상황

삭제된 redo group이 current가 되면 DB hang 또는 강제 종료 발생.

step1) 현재 redo 상태 확인
select a.group#,
       a.member,
       b.bytes/1024/1024 as "size(mb)",
       b.archived,
       b.status
from v$logfile a, v$log b
where a.group# = b.group#
order by 1;
step2) group 2(inactive & archive yes) 삭제 후
alter system switch logfile;

alter system checkpoint;
-- 2번은 active에서 inactive로 바꿔줌

$ rm /home/oracle/oradata/db1/redo02*
step3) log switch 여러 번 발생
alter system switch logfile;

ORA-00313: open failed for members of log group 2 of thread 1
ORA-00312: online log 2 thread 1: '/home/oracle/oradata/db1/redo02_2.log'
ORA-27041: unable to open file
ORA-00312: online log 2 thread 1: '/home/oracle/oradata/db1/redo02.log'
ORA-27041: unable to open file
-- 나는 DB hang(로그스위치에서 무한대기) 발생했음.
-- 다른 사람들은 DB 종료가 됨.
step4) 복구
-- case1) DB hang 된 경우 (DB online)
-- 현재 redo 상태 확인
> @/home/oracle/log.sql
-- group2가 current가 아님. 내 경우엔 group3이 current

-- group 삭제 시도
alter database drop logfile group 2;
ORA-00350: log 2 of instance db1 (thread 1) needs to be archived
ORA-00312: online log 2 thread 1: '/home/oracle/oradata/db1/redo02.log'
ORA-00312: online log 2 thread 1: '/home/oracle/oradata/db1/redo02_2.log'

-- group clear 시도 (성공할 수도 있고 실패할 수도 있음)
alter database clear unarchived logfile group 2;
-- 난 성공함. 아까 checkpoint를 만들어둬서 DBWR가 datafile을 내려썼기에 성공.
-- clear 성공하면 아까 rm으로 삭제헀던 파일이 생겨있음. 신기하다.
-- ** clear했으면 backup을 다시 받아야한다. 왜냐면 archive에 시퀀스정보가 없는 file이 생기기 때문에.

-- clear 안되면 recovery 진행해야 됨.
일단 flashback은 안됨(물리적 장애라서)
controlfile, datafile은 현재시점까지의 정보를 알고있는 상태고, current redo log에 기록될 변경 정보는 아직 반영되지 않은 상태(clear 불가). -> 현재 current redo log 정보 전까지만 복구 가능.(불완전복구)
백업본 + archive log file을 붙여가면서=recover해야 함.
step1) DB shutdown

step2) datafile restore
$ cp /oracle12/backup/cold_backup/*.dbf /home/oracle/oradata/db1

step3) 
recover database until cancel;  -- 불완전 복구 명령어
맨처음엔 엔터만.  -- 추천해준 archive file을 적용하겠다는 의미.
-- 만약 첫번째가 실패하면 경로를 직접 지정해줘야함.
-- 첫번째가 성공하면 뒤도 다 성공함. 그래서 이후엔
auto

-- 쭉 recover 되다가 current log였던 마지막 sequence의 차례가 되면 에러나면서 멈춤
alter database open resetlogs;
-- current log는 복구 안됐으니깐 resetlogs로 open. 불완전 복구는 resetlogs임.


-- case2) DB shutdown 된 경우 (shutdown abort)
-- 현재 redo 상태 확인
> startup mount
> @/home/oracle/log.sql
-- group2가 current임

-- group 삭제 시도 (current라서 실패)
alter database drop logfile group 2;
ORA-01623: log 2 is current log for instance db1 - cannot drop
ORA-00312: redo02.log
ORA-00312: redo02_2.log

-- group clear 시도 (성공할 수도 있고 실패할 수도 있음)
alter database clear unarchived logfile group 2;

-- clear 안되면 recovery 진행해야 됨. (위에 필기함)

[case3. current redo group 삭제 (DB 정상 종료)]

step1) 확인
select a.group#,
       a.member,
       b.bytes/1024/1024 as "size(mb)",
       b.archived,
       b.status
from v$logfile a, v$log b
where a.group# = b.group#
order by 1;
step2) group 3이 current가 될 때까지 log switch
alter system switch logfile;
step3) DML 발생
create table scott.recover_test1(no number);
insert into scott.recover_test1 values(1);
insert into scott.recover_test1 values(2);
insert into scott.recover_test1 values(3);
commit;  -- current redo file에 기록
step4) 장애 발생(current redo group 삭제) & shutdown immediate
$ rm /home/oracle/oradata/db1/redo03*

> shutdown immediate (정상 수행)

> startup
Database mounted.
ORA-03113: end-of-file on communication channel
Process ID: 13862
Session ID: 19 Serial number: 39367
-> 세션이 강제종료되어서 exit 후 재접속 해야됨
-- alert log
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03.log'
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03_2.log'
step5) 복구

clear 가 되면 clear로 복구하고, 안되면 recover로 복구

alter database clear unarchived logfile group 3;
-- 성공
alter database open;
-- cold backup 해놓기
step6) 데이터 확인
select * from scott.recover_test1;
-- 정상 출력됨.
-- shutdown immediate가 성공했다 -> global checkpoint가 생성됨 -> DBWR가 동작함 -> datafile에 잘 저장됨 -> clear 성공.

[case4. current redo group 삭제(DB 비정상 종료)]

DB가 올라올 때 해당 정보를 참고하여 복구 진행 불가 -> 장애 시점 이전까지만 복구 가능(불완전 복구)

step1) 현재 redo 상태 확인
select a.group#,
       a.member,
       b.bytes/1024/1024 as "size(mb)",
       b.archived,
       b.status
from v$logfile a, v$log b
where a.group# = b.group#
order by 1;
step2) group 1이 current & inactive가 되도록
alter system switch logfile;
alter system checkpoint;
step3) 데이터 입력
-- current가 group1일 때)
create table scott.recover_test2(no number);
insert into scott.recover_test2 values(1);
commit;
alter system switch logfile;
-- archiving & Thread checkpoint 발생 -> DBWR가 동작함

-- current가 group2일 때)
insert into scott.recover_test2 values(2);
commit;
alter system switch logfile;
step4) current redo group 삭제 & shutdown abort
-- current redo group이 뭔지 확인 후 해당 그룹 삭제
$rm /home/oracle/oradata/db1/redo03*

> shutdown abort

> startup
Database mounted.
ORA-00313: open failed for members of log group 3 of thread 1
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03_2.log'
ORA-27037: unable to obtain file status
Linux-x86_64 Error: 2: No such file or directory
Additional information: 7
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03.log'
ORA-27037: unable to obtain file status
Linux-x86_64 Error: 2: No such file or directory
Additional information: 7
-- alert log
Slave encountered ORA-10388 exception during crash recovery
ORA-00313: open failed for members of log group 3 of thread 1
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03_2.log'
ORA-27037: unable to obtain file status
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03.log'
ORA-27037: unable to obtain file status
ORA-313 signalled during: ALTER DATABASE OPEN...
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03.log'
ORA-27037: unable to obtain file status
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03_2.log'
ORA-27037: unable to obtain file status
step5) 복구

clear해보고 안되면 datafile restore -> recover -> db open

-- clear 시도 (실패)
alter database clear unarchived logfile group 3;
ORA-01624: log 3 needed for crash recovery of instance db1 (thread 1)
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03.log'
ORA-00312: online log 3 thread 1: '/home/oracle/oradata/db1/redo03_2.log'

-- dbf restore
$ cp /oracle12/backup/cold_backup/*.dbf /home/oracle/oradata/db1

-- recover
> startup mount
> recover database until cancel;

-- db open
> alter database open resetlogs;

-- 데이터 확인
select * from scott.recover_test2;

[case5. 전체 redo group 삭제 (DB운영 중->강제 종료)]

step1) 현재 redo 상태 확인
select a.group#,
       a.member,
       b.bytes/1024/1024 as "size(mb)",
       b.archived,
       b.status
from v$logfile a, v$log b
where a.group# = b.group#
order by 1;
step2) 데이터 입력
-- current group 1)
create table scott.recover_test3(no number);
insert into scott.recover_test3 values(1);
commit;
alter system switch logfile;

-- current group 2)
insert into scott.recover_test3 values(2);
commit;
alter system switch logfile;

-- current group 3)
insert into scott.recover_test3 values(3);
commit;
step3) 모든 redo log file 삭제
$ rm /home/oracle/oradata/db1/redo*

> alter system switch logfile;
-- alert log
ORA-27041: unable to open file
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: '/home/oracle/oradata/db1/redo01_2.log'
ORA-27041: unable to open file
ORA-00312: online log 1 thread 1: '/home/oracle/oradata/db1/redo01.log'
ORA-27041: unable to open file

ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 29467
Session ID: 249 Serial number: 34413
-- DB 종료됨.
step4-1) 복구 – DB hang된 경우
> startup mount

-- DB hang이었다면 가장 빠른 sequence#부터 순서대로 clear로 복구
alter database clear unarchived logfile group 3;
alter database clear unarchived logfile group 1;
alter database clear unarchived logfile group 2;  -- 실패
step4-2) DB shutdown된 경우

일단 log clear 시도한 뒤에.

$ cp /oracle12/backup/cold_backup/*.dbf /home/oracle/oradata/db1

> recover database until cancel;
엔터 후 auto엔터

> alter databasopen resetlogs;
step5) 데이터 조회
select * from scott.recover_test3;
-- 1,2 만 남고 3은 날라감.

[case6. 전체 controlfile, redo log file 삭제(shutdown abort)]

step1) 현재 상태 확인
select a.group#,
       a.member,
       b.bytes/1024/1024 as "size(mb)",
       b.archived,
       b.status
from v$logfile a, v$log b
where a.group# = b.group#
order by 1;
step2) 데이터 입력
-- current group 1)
create table scott.recover_test4(no number);
insert into scott.recover_test4 values(1);
commit;
alter system switch logfile;

-- current group 2)
insert into scott.recover_test4 values(2);
commit;
step3) 모든 controlfile, redo log file 삭제
$ rm /home/oracle/oradata/db1/*.ctl
$ rm /home/oracle/oradata/db1/*.log
step4) shutdown abort & startup
> shutdown abort
> startup
-- controlfile이 없으니 nomount단계에서 멈출거임
step5) 복구
-- 1. 실제로 controlfile이 없는지 확인
$ ll /home/oracle/oradata/db1

-- 2. nomount에서 mount로 가기 위해 controlfile 재생성
-- 근데 redo file이 없는 걸 확인했으니 resetlogs로 불완전 복구는 확정.
-- 따라서 그걸 가지고 재생성.
$ vi /oracle12/backup/cold_backup/control.sql
-- 써서 resetlogs 부분만 남기고 나머지 삭제.
> @/oracle12/backup/cold_backup/control.sql
-- controlfile 재생성 & 자동으로 mount 단계로 감
-- controlfile 이용해서 redologfile 상태 확인
> @/home/oracle12/log.sql
-- 만약 제대로 안되어있으면 그냥 backup본 가지고 restore하기.
-- 그리고 controlfile 재생성 했으니깐 temp 추가해주기

-- 3. datafile backup본 restore 후 recover 진행
$ cp /oracle12/backup/cold_backup/*.dbf
> recover database until cancel using backup controlfile

-- 4. db open
> alter database open resetlogs;
step6) 데이터 확인
select * from scott.recover_test4;

Leave a Comment