posted by 구름너머 2013. 3. 16. 16:53

# flashback table : 휴지통에서 테이블 복구


[hirasvr1:/SYSTEM/oraswno_datafile/DEVDB_DATA]$sqlplus '/as sysdba'

SQL*Plus: Release 10.2.0.2.0 - Production on Mon Dec 29 15:25:04 2008

Copyright (c) 1982, 2005, Oracle. All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

SQL> grant dba to hr ;


SQL> conn hr/hr
Connected.
SQL> create table emp1 (
2 ename varchar2(10),
3 id number(10)) ;

Table created.

SQL> insert into emp1 values ('aaa', 1) ;

1 row created.

SQL> insert into emp1 values ('bbb', 2) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> drop table emp1 ;

Table dropped.

SQL> show recyclebin <- 문제1) 무슨 명령어?
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
EMP1 BIN$XymNUHIAK3vgRAAAAAAAAA==$0 TABLE 2008-12-29:15:26:16

SQL> purge recyclebin; <- 문제2) 무슨 명령어?

Recyclebin purged.

SQL>
SQL> show recyclebin <-- 휴지통에 아무것도 없으니깐 아무것도 안나옴 ^^
SQL>

SQL> create table emp1 (
2 ename varchar2(10),
3 id number(10)) ;

Table created.

SQL> insert into emp1 values ('aaa', 1) ;

1 row created.

SQL> insert into emp1 values ('bbb', 2) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> drop table emp1 ;

Table dropped.

SQL> show recyclebin
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
EMP1 BIN$XymNUHIBK3vgRAAAAAAAAA==$0 TABLE 2008-12-29:15:33:13

SQL> flashback table emp1 to before drop;

Flashback complete.

SQL> select * from emp1 ;

ENAME ID
---------- ----------
aaa 1
bbb 2

SQL>
SQL> purge recyclebin;

Recyclebin purged.

SQL>
SQL> create table emp2 (
2 ename varchar2(10),
3 id number(10)) ;

Table created.

SQL> insert into emp2 values ('aaa', 1) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> drop table emp2 purge ; <- 문제3) 무슨 명령어?

Table dropped.

SQL> show recyclebin
SQL>

SQL> create table emp3 (
2 ename varchar2(10),
3 id number(10)) ;

Table created.

SQL> insert into emp3 values ('aaa', 1) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> create index index_emp3 on emp3(ename) ;

Index created.

SQL> select index_name from user_indexes where table_name = 'EMP3' ;

INDEX_NAME
------------------------------
INDEX_EMP3

SQL> drop table emp3 ;

Table dropped.

SQL> show recyclebin ;
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
EMP3 BIN$XymNUHIEK3vgRAAAAAAAAA==$0 TABLE 2008-12-29:15:55:10
SQL>
SQL> flashback table emp3 to before drop;

Flashback complete.

SQL> select * from emp3 ;

ENAME ID
---------- ----------
aaa 1

SQL> select index_name from user_indexes where table_name = 'EMP3' ;

INDEX_NAME
------------------------------
BIN$XymNUHIDK3vgRAAAAAAAAA==$0 <- 문제4) 이것은 무엇인가?

SQL> alter index "BIN$XymNUHIDK3vgRAAAAAAAAA==$0" rename to index_emp3 ; <- 문제5) 무슨 명령어?

Index altered.

SQL> select index_name from user_indexes where table_name = 'EMP3' ;

INDEX_NAME
------------------------------
INDEX_EMP3

SQL>


===========================================================================================
# flashback query : 과거 특정 시점의 데이터를 확인하고 그때로 돌아가자 ^^

-- 현제 시간과 DB 시간이 다를수 있으니, DB시간을 확인하고 DB시간에 맞춰 작업하세요 ^^

SQL> select to_char(sysdate, 'YYYY/MM/DD HH24:MI') from dual ;

SQL> select systimestamp from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
29-DEC-08 04.28.16.798523 PM +09:00

SQL> create table emp4 (
2 ename varchar2(10),
3 salary number(10)) ;

Table created.

SQL> insert into emp4 values ('namwon', 100) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> select systimestamp from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
29-DEC-08 04.31.08.784948 PM +09:00

SQL> select * from emp4 ;

ENAME SALARY
---------- ----------
namwon 100


SQL> update emp4
2 set salary=500
3 where ename='namwon' ;

1 row updated.

SQL> commit ;

Commit complete.

SQL> select * from emp4 ; <- 헉, 정남원을 급여가 100만원을 줘야 하는데 실수로 500만원을 줬다. 큰일큰일 ^^

ENAME SALARY
---------- ----------
namwon 500


SQL> select * from emp4 as of timestamp to_timestamp('2008-12-29 16:31','YYYY/MM/DD HH24:MI') ;

ENAME SALARY
---------- ----------
namwon 100


SQL> select * from emp4 as of timestamp to_timestamp('2008-12-29 16:35','YYYY/MM/DD HH24:MI') ;

ENAME SALARY
---------- ----------
namwon 100

SQL> select * from emp4 as of timestamp to_timestamp('2008-12-29 16:38','YYYY/MM/DD HH24:MI') ; <- 이 시간에 실수로 update 했구나.

ENAME SALARY
---------- ----------
namwon 500

SQL> update emp4 set salary = ( select salary from emp4
2 as of timestamp to_timestamp('2008-12-29 16:31','YYYY/MM/DD HH24:MI')
3 where ename='namwon' )
4 where ename='namwon';
<- 16:31 으로 빨리 돌아가자 ^^ 남원 급여는 100만원이야.ㅋㅋ

1 row updated.

SQL> commit ;

Commit complete.

SQL> select * from emp4 ;

ENAME SALARY
---------- ----------
namwon 100 <-- 정상적으로 100만원으로 돌아갔음 ^^

SQL>

=================================================================================================

# flashback version query : 과거 특정 기간(시간, SCN)의 이력 데이터 확인 및 그시점으로 flashback

SQL> conn hr/hr
Connected.
SQL> create table emp5 (
2 ename varchar2(10),
3 salary number(10)) ;

Table created.

SQL> insert into emp5 values ('NAMWON', 100);

1 row created.

SQL> insert into emp5 values ('KING', 1000) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> select * from emp5 ;

ENAME SALARY
---------- ----------
NAMWON 100
KING 1000

SQL> update emp5
2 set salary=200
3 where ename='NAMWON';

1 row updated.

SQL> update emp5
2 set salary=2000
3 where ename='KING' ;

1 row updated.

SQL> commit ;
Commit complete.

SQL> select * from emp5 ;

ENAME SALARY
---------- ----------
NAMWON 200
KING 2000


SQL> delete from emp5 ;

2 rows deleted.

SQL> commit ;

Commit complete.

SQL> select versions_startscn, versions_endscn, versions_operation, salary, ename
2 from emp5 versions between scn minvalue and maxvalue;

VERSIONS_STARTSCN VERSIONS_ENDSCN V SALARY ENAME
----------------- --------------- - ---------- ----------
968877 D 2000 KING
968877 D 200 NAMWON
967905 968877 U 2000 KING
967905 968877 U 200 NAMWON
967846 967905 I 1000 KING
967846 967905 I 100 NAMWON

6 rows selected.

SQL> alter table emp5 enable row movement ; <- rowid를 보전하지 않기 때문에 row movement 기능 활성화 되어 있어야함.

Table altered.

SQL> flashback table emp5 to scn 967846 ; <- 돌아가고 싶은 VERSIONS_STARTSCN 을 적으면 된다

Flashback complete.

SQL> select * from emp5 ;

ENAME SALARY
---------- ----------
NAMWON 100
KING 1000

SQL> flashback table emp5 to scn 967905 ;

Flashback complete.

SQL> select * from emp5 ;

ENAME SALARY
---------- ----------
NAMWON 200
KING 2000

SQL> flashback table emp5 to scn 968877 ;

Flashback complete.

SQL> select * from emp5 ;

no rows selected

SQL>

# flashback transaction query : 과거의 어떤 시간이나 SCN 사이의 존재 했던 행들의 값을 질의
트랜잭션에 의해 변화한 행들의 이력을 보여줌

SQL> conn hr/hr
Connected.

SQL> select supplemental_log_data_min from v$database;
SUPPLEME
--------
NO

SQL> alter database add supplemental log data;
Database altered.


SQL> select supplemental_log_data_min from v$database;
SUPPLEME
--------
YES

SQL> select current_scn from v$database;

CURRENT_SCN
-----------
972858


SQL> create table emp6(
2 ename varchar2(10),
3 salary number(10));

Table created.

SQL> insert into emp6 values ('NAMWON', 100) ;

1 row created.

SQL> insert into emp6 values ('KING', 1000);

1 row created.

SQL> insert into emp6 values ('ALICE', 300) ;

1 row created.

SQL> COMMIT ;

Commit complete.

SQL> update emp6
2 set salary=300
3 where ename='NAMWON' ;

1 row updated.

SQL> update emp6
2 set salary=3000
3 where ename='KING' ;

1 row updated.

SQL> commit ;

Commit complete.

SQL> delete from emp6 ;

3 rows deleted.

SQL> commit ;

Commit complete.

SQL> select versions_startscn, versions_endscn, versions_operation, salary, ename
2 from emp6 versions between scn minvalue and maxvalue;

VERSIONS_STARTSCN VERSIONS_ENDSCN V SALARY ENAME
----------------- --------------- - ---------- ----------
973006 D 300 ALICE
973006 D 3000 KING
973006 D 300 NAMWON
972999 973006 U 3000 KING
972999 973006 U 300 NAMWON
972964 973006 I 300 ALICE
972964 972999 I 1000 KING
972964 972999 I 100 NAMWON

8 rows selected.

SQL> select undo_sql from flashback_transaction_query
2 where table_name='EMP6'
3 and commit_scn between 972999 and 973006
4 order by start_timestamp desc;

UNDO_SQL
--------------------------------------------------------------------------------
insert into "HR"."EMP6"("ENAME","SALARY") values ('ALICE','300');
insert into "HR"."EMP6"("ENAME","SALARY") values ('KING','3000');
insert into "HR"."EMP6"("ENAME","SALARY") values ('NAMWON','300');
update "HR"."EMP6" set "SALARY" = '100' where ROWID = 'AAAM4tAAEAAABFEAAA';
update "HR"."EMP6" set "SALARY" = '1000' where ROWID = 'AAAM4tAAEAAABFEAAB';

SQL>


=================================================================================================

# flashback database : 전체 데이터베이스를 과거의 특정 시점으로 돌림

SQL> select flashback_on from v$database;

FLASHBACK_ON
------------------
NO

SQL> shutdown immediate
ORA-01031: insufficient privileges

SQL> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
[oracle@oracle ~]$ sqlplus '/as sysdba'

SQL*Plus: Release 10.2.0.1.0 - Production on Mon Dec 29 23:19:13 2008

Copyright (c) 1982, 2005, Oracle. All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount
ORACLE instance started.

Total System Global Area 167772160 bytes
Fixed Size 1218316 bytes
Variable Size 79694068 bytes
Database Buffers 83886080 bytes
Redo Buffers 2973696 bytes
Database mounted.
SQL> alter database flashback on ;

Database altered.

SQL> alter database open ;

Database altered.

SQL> select flashback_on from v$database;

FLASHBACK_ON
------------------
YES

SQL> alter system switch logfile ;

System altered.

SQL> select current_scn from v$database;

CURRENT_SCN
-----------
974236

SQL> drop user hr cascade ; <- 제가 젤로 아끼는 hr 유저 drop

User dropped.

SQL> conn hr/hr <- hr 유저가 drop 되서 접속 안됨 ㅠㅠ
ERROR:
ORA-01017: invalid username/password; logon denied

SQL> exit
[oracle@oracle ~]$ sqlplus '/as sysdba'

SQL*Plus: Release 10.2.0.1.0 - Production on Mon Dec 29 23:23:13 2008

Copyright (c) 1982, 2005, Oracle. All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL>
SQL> startup monut
SP2-0714: invalid combination of STARTUP options
SQL> startup mount
ORACLE instance started.

Total System Global Area 167772160 bytes
Fixed Size 1218316 bytes
Variable Size 88082676 bytes
Database Buffers 75497472 bytes
Redo Buffers 2973696 bytes
Database mounted.
SQL> flashback database to scn 974236 ; <- hr 유저 drop전 SCN번호 입력 (각자 환경마다 틀림 ^^)

Flashback complete.

SQL> alter database open resetlogs ;

Database altered.

SQL> conn hr/hr <- hr 유저 복원 ^^
Connected.
SQL>

====================================================================================

해답

SQL> show recyclebin <- 문제1) 무슨 명령어?
답) 휴지통 내용보기

SQL> purge recyclebin; <- 문제2) 무슨 명령어?
답) 휴지통 비우기(휴지통 삭제)

SQL> drop table emp2 purge ; <- 문제3) 무슨 명령어?
답) 테이블 drop 하면서 휴지통에도 동시에 삭제 (flashback 으로 복구 불가 ^^)

INDEX_NAME
------------------------------
BIN$XymNUHIDK3vgRAAAAAAAAA==$0 <- 문제4) 이것은 무엇인가?
답) 테이블이 삭제된후 휴지통으로 들어가면 인덱스명이 바뀐다. 그래서 원래 이름으로 rename 해야 한다 ^^

SQL> alter index "BIN$XymNUHIDK3vgRAAAAAAAAA==$0" rename to index_emp3 ; <- 문제5) 무슨 명령어?
답) 인덱스 이름 바꾸는 명령어

 

'ORACLE' 카테고리의 다른 글

Index monitoring usage  (0) 2013.03.26
INDEX 분석  (0) 2013.03.26
오라클 awr 리포트 뽑기  (0) 2013.03.13
Oracle 수업내용  (0) 2013.03.11
오라클 분석함수 rank(), max(), sum()  (0) 2012.09.17