data file 헤더에는 start scn과 stop scn이 있는데 정상적인 db 종료에는 종료시점의 checkpoint scn 번호가 입력되고 start scn과 stop scn이 동일하다.
그리고 다시 db open을 하게 되면 datafile 헤더의 start scn은 종료 scn이 그대로 들어있고 stop scn은 무한으로 설정되어있다.




v$recover_file : 현재 손상된 file이 어떤건지 확인하는 뷰

v$datafile 뷰를 통해 데이터파일 확인

ALTER DATABASE DATAFILE 오류데이터파일번호 offline drop;





recover datafile 손상데이터파일번호;
또는
recover tablespace 손상된 테이블스페이스 이름;
또는
ALTER DATABASE RECOVER DATAFILE 파일번호 or 파일주소;


offline 데이터파일 online으로 변경

데이터파일 상태 확인


CREATE TABLE hr.emp(id number) TABLESPACE example;
INSERT INTO hr.emp(id) VALUES(1);
COMMIT;





완전 복구가 될 생 각으로 recover 실행

- 마지막 백업 이후에 리두 정보를 이용해서 복구 작업을 시도 하려고 하는데 이미 리두로그는 로그스위치가 발생해서 변경된 정보들이 전부 없어져있다.
- noarchive log mode의 단점은 로그 스위치가 발생하면 리두 정보가 overwrite가 되어 버리기 때문에 완전복구를 할 수 없다.
아카이브 파일이 없기 때문에 auto를 해도 실패를 한다.

noarchive log mode에서 완전 복구를 할 수 없으면 컨트롤파일, 데이터파일, 리두로그 파일 전부를 restore 해야한다.
해결방법으로는 clone db에 백업파일을 통해 복구 한뒤 필요한 데이터파일만 export 한뒤 운영db에 import 하는 작업을 해야한다.





ALTER DATABASE CREATE DATAFILE '데이터파일주소' or 파일번호;









ALTER DATABASE CREATE DATAFILE '데이터파일주소' or 파일번호;










최근의 백업받은 system 데이터파일 restore 하기

백업이후에 변경정보를 이용해서 복구작업 recover(리두적용)

SELECT a.file#, b.name tbs_name, a.name file_name, a.status, a.checkpoint_change#
FROM v$datafile a, v$tablespace b
WHERE a.ts# = b.ts#;
SELECT * FROM v$log;


select segment_id , segment_name, owner, tablespace_name, status
from dba_rollback_segs;

UPDATE hr.employees SET salary = salary*1.1 WHERE employee_id = 100;
SELECT s.username, s.sid, s.serial#, r.name, t.xidusn, t.ubafil, t.ubablk, t.used_ublk
FROM v$session s, v$transaction t, v$rollname r
WHERE s.taddr = t.addr
AND t.xidusn = r.usn;

- 어느 유저에서 유입된 트랜잭션인지 확인할 때 사용된다.
- xidusn : undo segment 번호
- ubafil : 데이터파일 번호
- ubablk : undo block 번호
- used_ublk : undo block 사용 갯수




- undo 데이터파일이 online으로 나와있지만 실제로는 online 상태는 아니다.


SELECT a.file#, b.name tbs_name, a.name file_name, a.status, a.checkpoint_change#
FROM v$datafile a, v$tablespace b
WHERE a.ts# = b.ts#;
SELECT * FROM v$log;


select segment_id , segment_name, owner, tablespace_name, status
from dba_rollback_segs;

UPDATE hr.employees SET salary = salary*1.1 WHERE employee_id = 100;
SELECT s.username, s.sid, s.serial#, r.name, t.xidusn, t.ubafil, t.ubablk, t.used_ublk
FROM v$session s, v$transaction t, v$rollname r
WHERE s.taddr = t.addr
AND t.xidusn = r.usn;

- 어느 유저에서 유입된 트랜잭션인지 확인할 때 사용된다.
- xidusn : undo segment 번호
- ubafil : 데이터파일 번호
- ubablk : undo block 번호
- used_ublk : undo block 사용 갯수















SELECT a.file#, b.name tbs_name, a.name file_name, a.status, a.checkpoint_change#
FROM v$datafile a, v$tablespace b
WHERE a.ts# = b.ts#;
SELECT * FROM v$log;


select segment_id , segment_name, owner, tablespace_name, status
from dba_rollback_segs;

UPDATE hr.employees SET salary = salary*1.1 WHERE employee_id = 100;
SELECT s.username, s.sid, s.serial#, r.name, t.xidusn, t.ubafil, t.ubablk, t.used_ublk
FROM v$session s, v$transaction t, v$rollname r
WHERE s.taddr = t.addr
AND t.xidusn = r.usn;

- 어느 유저에서 유입된 트랜잭션인지 확인할 때 사용된다.
- xidusn : undo segment 번호
- ubafil : 데이터파일 번호
- ubablk : undo block 번호
- used_ublk : undo block 사용 갯수




- undo 데이터파일이 online으로 나와있지만 실제로는 online 상태는 아니다.


- 이전 HR 세션은 끊기고 새로운 HR세션으로 조회할때 100번사원의 이전값은 예전 undo 데이터파일에 있어서 새로운 CR 블록을 못만들기 때문에 조회 할 수가 없다.
create undo tablespace undo1 datafile '/u01/app/oracle/oradata/ORA19C/undo01.dbf' size 10m autoextend on;




SELECT segment_name || ','
FROM dba_rollback_segs
WHERE status = 'NEEDS RECOVERY';

CREATE PFILE FROM SPFILE

_offline_rollback_segments=(
_SYSSMU1_1261223759$,
_SYSSMU2_27624015$,
_SYSSMU3_2421748942$,
_SYSSMU4_625702278$,
_SYSSMU5_2101348960$,
_SYSSMU6_813816332$,
_SYSSMU7_2329891355$,
_SYSSMU8_399776867$,
_SYSSMU9_1692468413$,
_SYSSMU10_930580995$,
_SYSSMU11_2524835980$)




- 이후에는 정상적으로 employee_id = 100번의 데이터가 조회된다.

- 원복할때는 undo tablespace 기존 udnotbs1로 설정해주고 shut down 후 백업파일로 전체 restore 해주면 된다.

SELECT employee_id, salary FROM hr.employees ORDER BY 2 desc;
PGA메모리에서 소트작업을 할 용량이 되기 때문에 가능하다.
- 일부러 PGA메모리에 부하를 주기 위해 카테시안곱을 이용한 쿼리문을 던지기
SELECT s.*, b.*
FROM all_objects s, all_objects b
ORDER BY 1,2,3,4;

해당 쿼리문에만 문제가 생길 뿐 다른 문제는 없기때문에 세션에 영향을 주지는 않는다.
PGA에서 소트작업이 temp 데이터파일로 다이렉트로 내려가는데 temp 데이터파일이 없기때문에 오류가 발생한다.
SELECT property_value
FROM database_properties
WHERE property_name = 'DEFAULT_TEMP_TABLESPACE';
SELECT name FROM v$tempfile;


alter tablespace temp add tempfile '/u01/app/oracle/oradata/ORA19C/temp02.dbf' size 10m;

alter tablespace temp drop tempfile '/u01/app/oracle/oradata/ORA19C/temp01.dbf';

select b.tablespace, b.segfile#, b.segblk#, b.blocks, a.sid, a.serial#, a.username
from v$session a, v$sort_usage b
where a.saddr = b.session_addr;
조회되는 세션이 있다면 kill 시켜주면 된다.
alter system kill session 'sid,serial#' immediate;
SELECT s.*, b.*
FROM all_objects s, all_objects b
ORDER BY 1,2,3,4;

다시 오류가 발생하는데 이번 오류는 temp file의 크기가 작게 구성되어 있어서 temp segment를 확장할 수 없어서 생기는 오류이다.
1) temp file 크기조정
alter database tempfile '/u01/app/oracle/oradata/ORA19C/temp02.dbf' resize 100m;
2) 자동확장기능 활성화
alter database tempfile '/u01/app/oracle/oradata/ORA19C/temp02.dbf' autoextend on;

3) temp file 추가
alter tablespace temp add tempfile '/u01/app/oracle/oradata/ORA19C/temp01.dbf' size 10m autoextend on;

select name from v$tempfile;

select tablespace_name , contents from dba_tablespaces;

! rm /u01/app/oracle/oradata/ORA19C/temp01.dbf
! rm /u01/app/oracle/oradata/ORA19C/temp02.dbf
- tip : 네이밍이 똑같고 번호만 다를 경우 /u01/app/oracle/oradata/ORA19C/temp{01,02}.dbf 중괄호를 이용하면 된다.
일부러 PGA메모리에 부하를 주기 위해 카테시안곱을 이용한쿼리문을 던지기
SELECT s.*, b.*
FROM all_objects s, all_objects b
ORDER BY 1,2,3,4;

해당 쿼리문에만 문제가 생길 뿐 다른 문제는 없기때문에 세션에 영향을 주지는 않는다.,
PGA에서 소트작업이 temp 데이터파일로 다이렉트로 내려가는데 temp 데이터파일이 없기때문에 오류가 발생한다.
1) 새로운 temporary 테이블스페이스 생성
create temporary tablespace temp_new tempfile '/u01/app/oracle/oradata/ORA19C/temp_new01.dbf' size 10m autoextend on;
2) 디폴트 temporary로 설정
ALTER DATABASE default temporary tablespace temp_new;
- 변경된 값 조회
SELECT property_value
FROM database_properties
WHERE property_name = 'DEFAULT_TEMP_TABLESPACE';

select username, temporary_tablespace from dba_users;

3) 물리적으로 삭제된 temp 테이블스페이스 논리적으로 삭제
drop tablespace temp including contents and datafiles;

해당 오류가 발생 - 원인은 세션이 삭제하려는 temp 테이블스페이스를 잡고 있기 때문이다
원인 세션을 킬 해주면 된다.
ALTER SYSTEM KILL SESSION 'sid,serial#' immediate;
다시 한번 템프 데이터파일 확인해보기

SELECT name FROM v$tempfile;
SELECT property_value
FROM database_properties
WHERE property_name = 'DEFAULT_TEMP_TABLESPACE';


- 오라클이 템프 데이터파일이 없는걸 확인후 자동으로 템프 데이터파일을 생성한다.


- temp01.dbf는 분명 삭제하였는데 자동으로 생성되어있다.
- recreating 해서 생기는 temp 데이터파일은 control 파일에 설정되어있는 temp 설정값 그대로 만들어진다.

select name from v$datafile;

select name from v$tempfile;

select name from v$controlfile;

show parameter control_files

select member from v$logfile;


alter system checkpoint;




이전 컨트롤 파일의 위치
*.control_files='/u01/app/oracle/oradata/ORA19C/control01.ctl','/u01/app/oracle/fast_recovery_area/ORA19C/control02.ctl'
새로운 컨트롤 파일의 위치
*.control_files='/home/oracle/ora_data/control01.ctl'
새로운 위치의 컨트롤파일 주소로 변경



alter database rename file '이전파일' to '새로운파일';
alter database rename file '/u01/app/oracle/oradata/ORA19C/system01.dbf' to '/home/oracle/ora_data/system01.dbf';
alter database rename file '/u01/app/oracle/oradata/ORA19C/undotbs01.dbf' to '/home/oracle/ora_data/undotbs01.dbf';
alter database rename file '/u01/app/oracle/oradata/ORA19C/sysaux01.dbf' to '/home/oracle/ora_data/sysaux01.dbf';
alter database rename file '/u01/app/oracle/oradata/ORA19C/example01.dbf' to '/home/oracle/ora_data/example01.dbf';
alter database rename file '/u01/app/oracle/oradata/ORA19C/users01.dbf' to '/home/oracle/ora_data/users01.dbf';
alter database rename file '/u01/app/oracle/oradata/ORA19C/temp01.dbf' to '/home/oracle/ora_data/temp01.dbf';
alter database rename file '/u01/app/oracle/oradata/ORA19C/redo01.log' to '/home/oracle/ora_data/redo01.log';
alter database rename file '/u01/app/oracle/oradata/ORA19C/redo02.log' to '/home/oracle/ora_data/redo02.log';
alter database rename file '/u01/app/oracle/oradata/ORA19C/redo03.log' to '/home/oracle/ora_data/redo03.log';



mkdir -p /home/oracle/backup/noarch/20240827


CREATE TABLE hr.new(id number) TABLESPACE examplie;

INSERT INTO hr.new(id) VALUES(1);
COMMIT;










control 파일은 redo log 파일의 시퀀셜 번호 정보를 가지고 있는데 backup본 control 파일은 이전 redo log 시퀀셜 번호 정보를 가지고 있기 때문에 현재의 redo log 시퀀셜 번호랑은 매핑이 안된다.


recover database until cancel using backup controlfile;

ALTER DATABASE OPEN RESETLOGS;


SELECT b.file#, a.name as tbs_name, b.name as df_name, b.status, b.checkpoint_change#
FROM v$tablespace a, v$datafile b
WHERE a.ts# = b.ts#;

SELECT * FROM v$controlfile;

SELECT * FROM v$log;




- control file이 없기때문에 nomount 단계에서 mount 단계로 넘어갈 수 없다.





recover database using backup controlfile

SELECT a.group#, b.sequence#, a.member, b.bytes/1024/1024 MB, b.archived, b.status,b.first_time, b.next_time
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY 1;

- control 파일이 가지고 있는 이전 리두로그 정보를 볼 수 있다.

NORESETLOGS 옵션을 사용할 수 없다.RESETLOGS 옵션을 사용하여 DB OPEN을 하여야 하고 redo log의 시퀀셜 번호는 초기화 된다.

SELECT b.file#, a.name as tbs_name, b.name as df_name, b.status, b.checkpoint_change#
FROM v$tablespace a, v$datafile b
WHERE a.ts# = b.ts#;

SELECT * FROM v$controlfile;

SELECT * FROM v$log;





- control file이 없기때문에 nomount 단계에서 mount 단계로 넘어갈 수 없다.





SELECT a.group#, b.sequence#, a.member, b.bytes/1024/1024 MB, b.archived, b.status,b.first_time, b.next_time
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY 1;
recover database using backup controlfile

control 파일을 재 생성해야 할때
1) DB 이름을 변경할때
2) CONTROL 파일이 깨졌을때
3) MAX 옵션을 변경해야 할때controlfile로 trace 파일을 만들어야 할때
1) tablespace 구조가 바뀔때
2) redolog 구조가 바뀔때
alter database backup controlfile to trace as '파일주소/파일이름.sql';


MAXLOGFILES = 리두로그 그룹의 수MAXLOGMEMBERS = 하나의 그룹당 설정할 수 있는 멤버의 수MAXDATAFILES = 데이터베이스에서 생성할수 있는 데이터파일의 수MAXINSTANCES = 하나의 데이터베이스당 설정할 수 있는 인스턴스의 수MAXLOGHISTORY = 아카이브로그 파일을 생성할수 있는 수

noresetlogs로 open이 되었다. 

ALTER TABLESPACE TEMP ADD TEMPFILE '/u01/app/oracle/oradata/ORA19C/temp01.dbf' REUSE;
SELECT b.file#, a.name as tbs_name, b.name as df_name, b.status, b.checkpoint_change#
FROM v$tablespace a, v$datafile b
WHERE a.ts# = b.ts#;

SELECT * FROM v$controlfile;

SELECT * FROM v$log;




- 원래대로라면 오류가 발생해야 하는데 원래세션에서는 감지가 안된다.(오라클의 버그)

- 다른 세션에서 감지가 됬다.



control 파일을 재 생성해야 할때
1) DB 이름을 변경할때
2) CONTROL 파일이 깨졌을때
3) MAX 옵션을 변경해야 할때controlfile로 trace 파일을 만들어야 할때
1) tablespace 구조가 바뀔때
2) redolog 구조가 바뀔때
alter database backup controlfile to trace as '파일주소/파일이름.sql';


MAXLOGFILES = 리두로그 그룹의 수MAXLOGMEMBERS = 하나의 그룹당 설정할 수 있는 멤버의 수MAXDATAFILES = 데이터베이스에서 생성할수 있는 데이터파일의 수MAXINSTANCES = 하나의 데이터베이스당 설정할 수 있는 인스턴스의 수MAXLOGHISTORY = 아카이브로그 파일을 생성할수 있는 수






ALTER TABLESPACE TEMP ADD TEMPFILE '/u01/app/oracle/oradata/ORA19C/temp01.dbf' REUSE;

SELECT a.group#, b.sequence#, a.member, b.bytes/1024/1024 MB, b.archived, b.status,b.first_time, b.next_time
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY 1;









noresetlogs 옵션을 허용하지 않는다. resetlogs 옵션으로 실행해야한다.

SELECT a.group#, b.sequence#, a.member, b.bytes/1024/1024 MB, b.archived, b.status,b.first_time, b.next_time
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY 1;









SELECT a.group#, b.sequence#, a.member, b.bytes/1024/1024 MB, b.archived, b.status,b.first_time, b.next_time
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY 1;












CREATE CONTROLFILE REUSE DATABASE "ORA19C" RESETLOGS NOARCHIVELOG
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 292
LOGFILE
GROUP 1 '/u01/app/oracle/oradata/ORA19C/redo01.log' SIZE 200M BLOCKSIZE 512,
GROUP 2 '/u01/app/oracle/oradata/ORA19C/redo02.log' SIZE 200M BLOCKSIZE 512,
GROUP 3 '/u01/app/oracle/oradata/ORA19C/redo03.log' SIZE 200M BLOCKSIZE 512
DATAFILE
'/u01/app/oracle/oradata/ORA19C/system01.dbf',
'/u01/app/oracle/oradata/ORA19C/undotbs01.dbf',
'/u01/app/oracle/oradata/ORA19C/sysaux01.dbf',
'/u01/app/oracle/oradata/ORA19C/example01.dbf',
'/u01/app/oracle/oradata/ORA19C/users01.dbf'
CHARACTER SET AL32UTF8
;
ALTER DATABASE OPEN RESETLOGS;



SELECT a.group#, b.sequence#, a.member, b.bytes/1024/1024 MB, b.archived, b.status,b.first_time, b.next_time
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY 1;







shutdown abort 를 하면 data file들 끼리 checkpoint 수위가 안맞게 되어서 깨지게 되는데 이걸 다시 올릴때 만약 정상적인 리두 파일이 있다면 redo에 있는 checkpoint 정보를 가지고 자동으로 instance recovery를 해준다. 하지만 리두 로그 파일이 없다면 instance recovery를 해줄수 없기 때문에 data file을 restore 해줘야한다.
CREATE TABLESPACE data_tbs
DATAFILE '/u01/app/oracle/oradata/ORA19C/data01.dbf' size 5m
EXTENT MANAGEMENT local uniform size 64k
SEGMENT SPACE MANAGEMENT AUTO;

- data01.dbf 파일은 db open 후 생성하였기 때문에 checkpoint가 다르다
새로 만든 테이블스페이스에 생성한다.

리두 정보 확인
SELECT a.group#, b.sequence#, a.member, b.bytes/1024/1024 MB, b.archived, b.status,b.first_time, b.next_time
FROM v$logfile a, v$log b
WHERE a.group# = b.group#
ORDER BY 1;










trace 파일 생성 시도를 recover을 시도한 뒤에 한 이유는 redo정보가 가지고 있는 원래의 컨트롤 파일의 정보가 있는데 백업 컨트롤 파일에는 정보가 없기 때문에 백업컨트롤 파일에 알수없는 이름의 데이터파일을 생성한다.



CREATE CONTROLFILE REUSE DATABASE "ORA19C" NORESETLOGS NOARCHIVELOG
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 292
LOGFILE
GROUP 1 '/u01/app/oracle/oradata/ORA19C/redo01.log' SIZE 200M BLOCKSIZE 512,
GROUP 2 '/u01/app/oracle/oradata/ORA19C/redo02.log' SIZE 200M BLOCKSIZE 512,
GROUP 3 '/u01/app/oracle/oradata/ORA19C/redo03.log' SIZE 200M BLOCKSIZE 512
DATAFILE
'/u01/app/oracle/oradata/ORA19C/system01.dbf',
'/u01/app/oracle/oradata/ORA19C/undotbs01.dbf',
'/u01/app/oracle/oradata/ORA19C/sysaux01.dbf',
/*'/u01/app/oracle/product/19.3.0/dbhome_1/dbs/UNNAMED00004' 이전에 recover을 시도 했기 때문에 redo가 만들어놓은 논리적인 주소이다.*/
'/u01/app/oracle/oradata/ORA19C/data01.dbf', -- 실제 주소로 수정해서 입력
'/u01/app/oracle/oradata/ORA19C/example01.dbf',
'/u01/app/oracle/oradata/ORA19C/users01.dbf'
CHARACTER SET AL32UTF8
;
ALTER DATABASE OPEN;
ALTER TABLESPACE TEMP ADD TEMPFILE '/u01/app/oracle/oradata/ORA19C/temp01.dbf' REUSE;
