- yagom's blog
- 배움에 길에는 끝이 없다.
- Naked Foot
- SAP PP
- SAP ABAP
- SAP BSP
- SAP Inside
- 자바지기
- SECRET OF KOREA
- X-Mobile User Interface World
- 대한민국 자식연합
- 대한민국 토리스토리
- Malus domestica
- PCPINSIDE(거리로 PC, 거실로 PC)
- My Eyes on You
- 조대협의 블로그
- 릴리펏's Logbook
- Dr. Ann(닥터앤)의 DB이야기
- 디지털을 말한다. By oojoo
- Slow Adopter
- T.B 의 SNS 이야기
- Sense and Sensibility
- 언제나 Burning~
- 바스토프의 세상이야기
- Edu&Story
- Min.Gun
- freestation
- nigh
- Programmer
- Shine A Light
- 하루 벌어 하루 살아요. ㅋㅋ
- 아이캐리즈
- 오라클 성능 문제에 대한 통찰 - 조동욱
- 에너쓰오라클
- Science of DataBase
- 기억을 글로 담기
- 홍기선's 아키텍트 이야기 그리고
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- semi join
- nested loops join
- 스폰서 요금제
- EA
- ERP
- A2P
- zero rating
- oracle tuning
- java
- Analytic Function
- AWS Elastic Beanstalk
- Database
- oracle
- RBM
- MSSQL SQL
- OUTER JOIN
- Annualized Failure Rate
- JDBC
- tuning
- cluster table
- ORACLE SQL
- PostgreSQL
- ansi query
- Mean Time Between Failures
- Table
- data pump
- Network Neutrality
- index-organized table
- aws
- MTBF
- Today
- Total
아이짱구
Flashback Technology 본문
Oracle Database 10g 부터 지원하는 Flashback 기술은 사용자의 실수를 해결하기 위해 등장한 새로운 기능이다. 실수로 테이블을 삭제 했거나 잘못 실행 된 DML 문장을 COMMIT 시켰을 경우 보다 손 쉽게 이전 상태로 되돌리 수 있는 기능이다.
사용자의 실수 또는 응용 프로그램의 오류로 인해 논리적 손상이 발생한 경우 빠르고 쉽게 Recovery를 지원한다.
- Flashback Database: Flashback Log를 이용하여 불완전 복구를 손쉽게 수행
- Flashback Table: Undo Data를 이용하여 Table을 과거 시점으로 복구
- Flashback DROP: Recycle bin을 이용하여 DROP 된 Table 복구
- Flashback Query: 과거의 특정 시점의 Data를 쿼리 (Undo Data 활용)
- Flashback Version Query: 여러 트랜잭션의 각 버전별 상태 확인 (Undo Data 활용)
- Flashback Transaction Query: 특정 트랜잭션의 Undo SQL 생성 (Undo Data 활용)
- Flashback Transaction: 특정 트랜잭션을 복구 (Undo, Redo Data 활용)
- Flashback Data Archive: 트랜잭션의 데이터를 보다 장시간 동안 유지 (Undo Data 활용)
Flashback Query
이전 시점을 확인 하기 위해서 현재의 시간 및 SCN을 확인 한다.
SCN(System Change Number): Database는 운영되는 도중 수 많은 명령문들이 실행되고 있으며, 그때마다 일률적으로 증가되는 Number를 부여하게 되므로 명령문들의 순서 및 시점을 확인 할 수 있다.
[orcl:~]$ . oraenv
ORACLE_SID = [orcl] ? orcl
The Oracle base for ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 is /u01/app/oracle
[orcl:~]$ sqlplus / as sysdba
SQL> alter user scott identified by tiger account unlock ;
SQL> conn scott/tiger
SQL> set linesize 150
SQL> CONN system/oracle
SQL> SELECT TO_CHAR(SYSDATE, 'DD-MON-RR HH24:MI:SS') AS SCN_DATE FROM dual;
SCN_DATE
------------------
20-APR-10 00:44:38
SQL> SELECT current_scn FROM v$database;
CURRENT_SCN
-----------
686299
현재 정보를 확인 한다.
SQL> SELECT empno
, ename
, sal
, deptno
FROM emp
WHERE empno = 7788;
EMPNO ENAME SAL DEPTNO
----- ----- ---- ------
7788 SCOTT 3000 20
SQL> UPDATE emp
SET sal = sal * 1.2
WHERE empno = 7788;
SQL> COMMIT;
상기 UPDATE DML 문장을 통해서 데이터 수정 및 COMMIT한 상태로 ROLLBACK이 불가능한 상태이다.
SQL> SELECT empno
, ename
, sal
, deptno
FROM emp
WHERE empno = 7788;
EMPNO ENAME SAL DEPTNO
----- ----- ---- ------
7788 SCOTT 3600 20
모든 세션은 COMMIT 된 3600의 결과를 확인 할 수 있다. 하지만 이러한 DML이 사용자의 실수로 인해 잘못 수정된 값이라면, ROLLBACK도 불가능하므로 이전 값으로 되돌리기가 까다로울 수 있다.
모든 DML은 값의 수정을 진행하면서 Undo Data가 생성된다. Oracle Database 10g 이전까지는 Undo Data를 따로 접근 가능한 방법이 존재하지 않았으나 이후로는 가능하다.
FLASHBACK Query(Oracle Database 9i 부터 지원)는 아존 시점의 Data를 확인 할 수 있는 Query이며 COMMIT이 진행 되었더라도 Undo Data를 확인 할 수 있게 해준다.
SQL> SELECT empno
, ename
, sal
, deptno
FROM emp AS OF TIMESTAMP TO_DATE('20-APR-10 00:44:38', 'DD-MON-RR HH24:MI:SS')
WHERE empno = 7788;
EMPNO ENAME SAL DEPTNO
----- ----- ---- ------
7788 SCOTT 3000 20
SQL> SELECT empno
, ename
, sal
, deptno
FROM emp AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '5' MINUTE))
WHERE empno = 7788;
SQL> SELECT empno
, ename
, sal
, deptno
FROM emp AS OF SCN 626299
WHERE empno = 7788;
위의 문장 모두 동일한 결과를 가져 올 수 있다. 이렇듯 Flashback Query를 사용하면 특정 시점을 지정하여 필요한 이전 상태의 정보를 확인 할 수 있다. 단, Undo Data가 존재하는 경우 가능하다.
Data가 반복되는 DML에 의해서 계속 변경되고 있다면, 변경 되는 상태 전체를 확인 가능하다.
SQL> UPDATE emp
SET sal = sal * 1.2
WHERE empno = 7788;
SQL> COMMIT;
SQL> UPDATE emp
SET sal = sal * 1.2
WHERE empno = 7788;
SQL> COMMIT;
SQL> UPDATE emp
SET sal = sal * 1.2
WHERE empno = 7788;
SQL> COMMIT;
동일한 상원번호에 대하여 반복적인 UPDATE가 진행 되었다. COMMIT이 계속 진행 되었으므로 검색을 해 보면 최종 UPDATE 된 정보를 확인 할 수 있다. 하지만 변경을 진행하는 각 과정(version)에 대한 정보를 확인하고 싶다면?
SQL> SELECT TO_CHAR(SYSDATE, 'DD-MON-RR HH24:MI:SS') AS SCN_DATE FROM dual;
SCN_DATE
------------------
20-APR-10 00:47:01
SQL> SELECT current_scn FROM v$database;
CURRENT_SCN
-----------
686356
시점을 확인 하기 위해서 현재의 시간 정보 및 SCN 확인.
SQL> SELECT empno
, sal
, versions_starttime
, versions_endtime
, versions_operation
FROM emp VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE
WHERE empno = 7788;
EMPNO SAL VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_OPERATION
----- ------ --------------------- --------------------- ------------------
7788 6220.8 20-APR-10 12.46.27 AM U
7788 5184 20-APR-10 12.46.15 AM 20-APR-10 12.46.27 AM U
7788 4320 20-APR-10 12.46.15 AM 20-APR-10 12.46.15 AM U
7788 3600 20-APR-10 12.44.59 AM 20-APR-10 12.46.15 AM U
7788 3000 20-APR-10 12.44.59 AM
Flashback Version Query를 사용하면 된다. Version Query는 시간(TIMESTAMP) 또는 SCN을 기반으로 범위를 지정하며, 해당 범위 내의 변경 내역을 확인 할 수 있다. 이때 각 버전의 시작시간(versions_starttime)및 종료시간(versions_endtime)과 어떤 작업이 진행 되었는지(version_operation)를 함계 확인 할 수 있다. MINVALUE와 MAXVALUE는 접근 가능한 최소, 최대의 시간을 가져 올 수 있다(접근 가능한 Undo Data의 범위 까지).
SQL> SELECT empno
, sal
, versions_starttime
, versions_endtime
, versions_operation
FROM emp VERSIONS BETWEEN TIMESTAMP TO_DATE('20-APR-10 00:44:38', 'DD-MON-RR HH24:MI:SS')
AND TO_DATE('20-APR-10 00:47:01', 'DD-MON-RR HH24:MI:SS')
WHERE empno = 7788;
동일한 결과를 가져올 수 있는 문장이다. MINVALUE, MAXVALUE를 사용하지 않고 원하는 시간을 지정할 수 있다.
SCN을 기반으로 동일한 결과를 확인 할 수 있다. 각 버전의 시작, 종료 시간 외에도 versions_startscn, versions_enscn을 함께 검색할 수 있다.
SQL> SELECT empno
, sal
, versions_startscn
, versions_endscn
, versions_operation
FROM emp VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
WHERE empno = 7788;
EMPNO SAL VERSIONS_STARTSCN VERSIONS_ENDSCN VERSIONS_OPERATION
----- ------ ----------------- --------------- ------------------
7788 6220.8 686337 U
7788 5184 686333 686337 U
7788 4320 686331 686333 U
7788 3600 686305 686331 U
7788 3000 686305
SQL> SELECT empno
, sal
, versions_starttime
, versions_endtime
, versions_operation
FROM emp VERSIONS BETWEEN SCN 686299 AND 686356
WHERE empno = 7788;
이렇게 COMMIT이 진행된 DML의 이전 Data를 확인 할 수 있다는 것은 필요 시 이전 상태로 되돌리는 것도 보다 쉽게 가능하다(뒤에서 FLASHBACK TABLE 명령 확인)..
SQL> UPDATE emp
SET sal = (SELECT sal
FROM emp AS OF TIMESTAMP (SYSDATE - INTERVAL '10' MINUTE)
WHERE empno = 7788)
WHERE empno = 7788;
SQL> SELECT empno
, sal
FROM empno = 7788;
EMPNO SAL
----- ----
7788 3000
SQL> COMMIT;
Flashback Query와 Version Query를 이용하면 특정 시점 및 변경 되는 각 버전의 상태를 확인 할 수 있다. 또한 이를 이용해서 이전 시점으로 손 쉽게 되돌아 갈 수도 있다.
Transaction Query는 변화되고 있는 각 Data를 이전으로 되돌릴 수 있는 명령문(DML) 문장을 만들어 주는 Query 이다(FLASHBACK_TRANSACTION_QUERY의 분류 Query 해야 하기 때문에 FLASHBACK_TRANSACTION_QUERY의 SELECT 권한 필요).
SQL> SELECT * FROM dept;
DEPTNO DNAME LOC
------ ---------- -------
10 ACCOUNTING NEWYORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
현재 상태를 확인한다. 그 뒤 여러 DML 문장을 실행 시키고 각각 COMMIT도 진행한다..
SQL> DELETE dept WHERE deptno = 40;
SQL> UPDATE dept
SET loc = 'SEOUL'
WHERE deptno = 10;
SQL> COMMIT;
SQL> INSERT INTO dept
VALUES (50, 'MARKETTING', 'BUSAN');
SQL> UPDATE dept
SET loc = 'JEJU'
WHERE deptno = 10;
SQL> COMMIT;
전체 4개의 DML 문장이 실행 되었으며 두 개의 Transaction으로 나뉘어 실행 되었다.
SQL> SELECT * FROM dept;
DEPTNO DNAME LOC
------ ---------- -------
50 MARKETTING BUSAN
10 ACCOUNTING JEJU
20 RESEARCH DALLAS
30 SALES CHICAGO
SQL> SELECT deptno
, dname
, loc
, versions_xid AS XID
, versions_startscn AS START_SCN
, versions_endscn AS END_SCN
, versions_operation AS OP
FROM emp VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
DEPTNO DNAME LOC XID START_SCN END_SCN OP
------ ---------- ------- ---------------- --------- -------- --
50 MARKETTING BUSAN 06001A0078010000 692534 I
40 OPERATIONS BOSTON 0200190065010000 692529 D
40 OPERATIONS BOSTON 692529
10 ACCOUNTING JEJU 06001A0078010000 692534 U
10 ACCOUNTING SEOUL 0200190065010000 692529 692534 U
10 ACCOUNTING NEWYORK 692529
20 RESEARCH DALLAS
30 SALES CHICAGO
VERSION Query를 이용하여 DEPT 테이블의 값들이 어떻게 변경 되었는지를 확인한다. versions_xid는 Transaction ID이며 어떤 명령문이 어떤 순서로 실행 되었는지를 확인 할 수 있다.
이제 FLASHBACK_TRANSACTION_QUERY를 확인하여 UNDO SQL을 확인 한다. 위에서 확인 한 transaction id를 이용하여 특정 transaction에서 진행된 명령문의 UNDO SQL 만 확인 할 수 있다.
SQL> SELECT start_scn
, commit_scn
, operation_sql
FROM FLASHBACK_TRANSACTION_QUERY
WHERE xid = HEXTORAW('&XID');
Enter value for xid: 06001A0078010000
START_SCN COMMIT_SCN OPERATION UNDO_SQL
--------- ---------- --------- ----------------
692530 692534 UPDATE UPDATE DEPT SET LOC = 'SEOUL' WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
692530 692534 DELETE DELETE FROM DEPT WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
Version Query에서 확인 했던 XID 값을 이용한다.
SQL> SELECT undo_sql
FROM FLASHBACK_TRANSACTION_QUERY
WHERE table_owner = 'SCOTT'
AND table_name = 'DEPT'
AND start_timestamp >= SYSTIMESTAMP - INTERVAL '10' MINUTE;
UNDO-SQL
--------------------------------------------------------------------------
UPDATE DEPT SET LOC = 'NEWYORK' WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
INSERT INTO DEPT (DEPTNO, DNAME, LOC) VALUES (40, 'OPERATIONS', 'BOSTON');
UPDATE DEPT SET LOC = 'SEOUL' WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
DELETE FROM DEPT WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
START_TIMESTAMP, TABLE_OWNER, TABLE_NAME 등을 이용하여 원하는 시간 및 테이블에 접근했던 문장들의 UNDO SQL을 검색할 수 있다.
SQL> SELECT undo_sql
FROM FLASHBACK_TRANSACTION_QUERY
WHERE xid IN (SELECT versions_xid FROM dept VERSIONS BETWEEN SCN MINVAL AND MAXVALUE);
UNDO-SQL
--------------------------------------------------------------------------
UPDATE DEPT SET LOC = 'SEOUL' WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
DELETE FROM DEPT WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
UPDATE DEPT SET LOC = 'NEWYORK' WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
INSERT INTO DEPT (DEPTNO, DNAME, LOC) VALUES (40, 'OPERATIONS', 'BOSTON');
또는 Version Query를 통해서 얻을 수 있는 XID(Transaction ID)를 Subquery로 이용해도 동일한 결과를 구할 수 있다.
검색 된 Undo SQL들 중 필요한 문장만 복사해서 실행하면 이전 상태로 되돌릴 수 있다.
SQL> DELETE FROM DEPT WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
SQL> UPDATE DEPT SET LOC = 'NEWYORK' WHERE ROWID = 'AAAMfKAAEAAAAAQAAA';
SQL> INSERT INTO DEPT (DEPTNO, DNAME, LOC) VALUES (40, 'OPERATIONS', 'BOSTON');
SQL> COMMIT;
SQL> SELECT * FROM dept;
DEPTNO DNAME LOC
------ ---------- -------
40 OPERATIONS BOSTON
10 ACCOUNTING NEWYORK
20 RESEARCH DALLAS
30 SALES CHICAGO
Flashback Table ( Recyclebin )
Flashback Table은 지정된 테이블을 과거의 시점으로 되돌리거나 삭제된 테이블을 삭제되기 이전 상태로 되돌릴 수 있는 기능이다. 우선은 DROP 된 테이블을 되살릴 수 있는 기능부터 확인 해 보자.
실습을 위해서 새로운 테이블스페이스 및 테이블들을 생성한다.
SQL> CONN system/oracle
SQL> CREATE TABLESPACE tbs
DATAFILE 'test01.dbf' SIZE 10M AUTOEXTEND ON MAXSIZE 20M
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
Locally Management Tablespace를 생성하며, Uniform Size는 1MB로 지정한다. 최초 크기는 10MB이며, 20MB까지 자동확장 가능하게 설정한다.
SQL> CREATE TABLE emp
TABLESPACE tbs
STORAGE (MINEXTENTS 2)
AS SELECT * FROM emp;
SQL> CREATE TABLE dept
TABLESPACE tbs
STORAGE (MINEXTENTS 2)
AS SELECT * FROM dept;
두 개의 테이블을 생성하며 각각 Extent를 2개씩 할당 받는다.
SQL> CREATE TABLE test
TABLESPACE tbs
AS SELECT * FROM emp;
SQL> CREATE INDEX test_idx ON test (empno)
TABLESPACE tbs;
실습에 필요한 TEST 테이블을 생성하며 Index도 함께 생성한다..
SQL> ALTER TABLE test
ADD PRIMARY KEY (empno);
SQL> CREATE TRIGGER test_trig
AFTER INERT ON test
BEGIN
NULL;
END;
/
추가적으로 제약조건 및 Trigger도 생성하였다.
SQL> SELECT object_name
, object_id
, object_type
, status
FROM user_objects
WHERE created > SYSDATE - INTERVAL '5' MINUTE;
OBJECT_NAME OBJECT_ID OBJECT_TYPE STATUS
----------- --------- ----------- ------
EMP 52686 TABLE VALID
DEPT 52687 TABLE VALID
TEST 52688 TABLE VALID
TEST_IDX 52689 INDEX VALID
TEST_TRIG 52690 TRIGGER VALID
현재 생성된 Object 들이다.
SQL> SELECT constraint_name
, constraint_type
FROM user_constraints
WHERE table_name = 'TEST';
CONSTRAINTS_NAME CONSTRAINTS_TYPE
---------------- ----------------
SYS_C005443 P
TEST 테이블에 추가된 제약 조건의 이름을 확인 한다.
SQL> SELECT *
FROM dba_free_space
WHERE tablespace_name = 'TBS':
TABLESPACE FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
---------- ------- -------- ------- ------ ------------
TBS 6 777 3145728 384 6
TBS 테이블스페이스에는 여러 Object들이 생성 되었으므로 Free Space도 줄어 들어 있는 것을 확인 한다. 현재 상태는 Block ID 777부터 384개의 3MB의 여유 공간이 존재한다.
SQL> SELECT segment_name
, extent_id
, block_id
, blocks
FROM dba_extents
WHERE tablespace_name = 'TBS';
SEGMENT_NAME EXTENT_ID BLOCK_ID BYTES BLOCKS
------------ --------- -------- ------- ------
EMP 0 9 1048576 128
EMP 1 137 1048576 128
DEPT 0 265 1048576 128
DEPT 1 393 1048576 128
TEST 0 521 1048576 128
TEST_IDX 0 649 1048576 128
TBS 테이블스페이스에 생성된 Object들이 어떻게 공간을 소모하고 있는지 확인한다(Enterprise Manager의 Extent Map).
확인 될 결과 해당 테이블스페이스의 마지막 3MB가 여유공간으로 남아 있으며 앞의 공간들은 모두 사용되고 있는 것을 확인 할 수 있다.
SQL> DROP TABLE test;
SQL> SELECT * FROM test;
ERROR at line 1;
ORA-00942: table or view does not exist
테이블을 삭제 하였다. 때문에 TEST 테이블을 통한 검색 및 어떠한 DML도 실행할 수 없다. 각각의 뷰를 확인하여 어떻게 처리되고 있는지를 확인한다.
SQL> SELECT *
FROM dba_free_space
WHERE tablespace_name = 'TBS':
TABLESPACE FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
---------- ------- -------- ------- ------ ------------
TBS 6 777 3145728 384 6
TBS 6 649 1048576 128 6
TBS 6 521 1048576 128 6
TEST와 관련된 정보는 DBA_EXTENTS 뷰를 통해서도 확인 할 수 없다.
SQL> SELECT object_name
, object_id
, object_type
, status
FROM user_objects
WHERE created > SYSDATE - INTERVAL '1' HOUR;
OBJECT_NAME OBJECT_ID OBJECT_TYPE STATUS
------------------------------ --------- ----------- --------
EMP 52686 TABLE VALID
DEPT 52687 TABLE VALID
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 52688 TABLE VALID
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 52689 INDEX VALID
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 52690 TRIGGER INVALID
하지만 삭제된 TEST 테이블과 관련된 Object 공간은 삭제된 것처럼 보이지만 이름만 변경된 것을 확인 할 수 있다.
SQL> SELECT constraint_name
, constraint_type
FROM user_constraints
WHERE table_name = 'TEST';
CONSTRAINTS_NAME CONSTRAINTS_TYPE
------------------------------ ----------------
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 P
제약 조건 역시 이름이 변경 되었다.
SQL> SHOW RECYCLEBIN
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
------------- ------------------------------ ----------- -------------------
TEST BIN$hjvE20sxQhPgQKjAZGQmEw==$0 TABLE 2012-08-28:08:22:38
RECYCLEBIN을 확인 해 보면 TEST 테이블이 언제 삭제 되었는지, 변경된 이름이 무엇인지 확인 가능하다. Oracle Database 10g 부터는 테이블을 삭제하면 보다 손쉬운 복구를 위해서 이름을 변경한다.
SQL> SELECT object_name
, original_name
, type
, can_undrop
FROM recyclebin;
OBJECT_NAME ORIGINAL_NAME TYPE CAN_UNDROP
------------------------------ ------------- ------- ----------
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 TEST TABLE NO
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 TEST_IDX INDEX NO
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 TEST_TRIG TRIGGER YES
보다 상세한 정보는 RECYCLEBIN 뷰를 통해 확인 가능하다.
Extent Map을 확인 해 보면 삭제된 공간을 Unmapped로 처리하고 있다. 이제 삭제된 테이블 TEST를 복구하는 방법은 아래와 같다.
SQL> FLASHBACK TABLE test TO BEFORE DROP;
SQL> SELECT * FROM test;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ----- -------- ---- --------- ---- ---- ------
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7566 JONES MANAGER 7839 02-APR-81 2975 20
SQL> SELECT object_name
, object_id
, object_type
, status
FROM user_objects
WHERE created > SYSDATE - INTERVAL '1' HOUR;
OBJECT_NAME OBJECT_ID OBJECT_TYPE STATUS
------------------------------ --------- ----------- --------
EMP 52686 TABLE VALID
DEPT 52687 TABLE VALID
TEST 52688 TABLE VALID
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 52689 INDEX VALID
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 52690 TRIGGER INVALID
SQL> SELECT constraint_name
, constraint_type
FROM user_constraints
WHERE table_name = 'TEST';
CONSTRAINTS_NAME CONSTRAINTS_TYPE
------------------------------ ----------------
BIN$hjvE20sxQhPgQKjAZGQmEw==$0 P
하지만 테이블을 제외한 다른 Object 및 제약 조건은 원래의 이름으로 되돌아 가지 않는다.
삭제된 테이블을 복구 할 때 다른 이름으로 복구를 하려면 RENAME 절을 사용한다..
SQL> FLASHBACK TABLE test TO BEFORE DROP RENAME TO test2;
동일한 이름이 많아 혼동이 될 때는 아래와 같이 현재 이름을 이용해도 된다. 단, 이때 테이블의 이름은 큰 따옴표로 묶어야 한다..
SQL> FLASHBACK TABLE "BIN$hjvE20sxQhPgQKjAZGQmEw==$0" TO BEFORE DROP;
SQL> DROP TABLE test;
SQL> SHOW RECYCLEBIN;
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
------------- ------------------------------ ----------- -------------------
TEST BIN$hjvE20sxQhPgQKjAZGQmEw==$0 TABLE 2012-08-28:08:22:38
SQL> SELECT * FROM "BIN$hjvE20sxQhPgQKjAZGQmEw==$0";
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ----- -------- ---- --------- ---- ---- ------
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7566 JONES MANAGER 7839 02-APR-81 2975 20
삭제가 된 상태에서도 SELECT를 통하여 Data의 검증이 가능하다.
TEST 테이블을 다시 삭제 한 상태이다. 이때 공간의 할당은 해제 되지 않고 이름만 변경 한다고 하였다. 그렇다면 TBS 테이블스페이스의 다른 Object들이 공간을 늘려 가거나 새로운 Object가 생성 된다면 어떻게 될까?
SQL> ALTER TABLE emp ALLOCATE EXTENT;
SQL> ALTER TABLE dept ALLOCATE EXTENT;
SQL> CREATE TABLE salgrade
TABLESPACE tbs
AS SELECT * FROM salgrade;
SQL> SELECT segment_name
, extent_id
, block_id
, bytes
, blocks
FROM dba_extents
WHERE tablespace_name = 'TBS';
SEGMENT_NAME EXTENT_ID BLOCK_ID BYTES BLOCKS
------------ --------- -------- ------- ------
EMP 0 9 1048576 128
EMP 1 137 1048576 128
EMP 2 777 1048576 128
DEPT 0 265 1048576 128
DEPT 1 393 1048576 128
DEPT 2 905 1048576 128
SALGRADE 0 1033 1048576 128
SQL> SELECT *
FROM dba_free_space
WHERE tablespace_name = 'TBS':
TABLESPACE FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
---------- ------- -------- ------- ------ ------------
TBS 6 649 1048576 128 6
TBS 6 521 1048576 128 6
삭제 된 TEST 테이블이 차지하고 있는 공간은 그대로 남겨두고 원래 빈 공간으로 남아 있던 영역을 사용하는 것을 확인 할 수 있다. 하지만 원래 있던 빈 공간 3MB는 다 사용된 상태이다. 여기서 추가적인 Extent가 필요하면 어떻게 될까? TBS 테이블스페이스는 자동확장 기능을 사용하고 있기 때문에 20MB까지 추가 확장은 가능하다.
SQL> ALTER TABLE emp ALLOCATE EXTENT;
SQL> SELECT segment_name
, extent_id
, block_id
, bytes
, blocks
FROM dba_extents
WHERE tablespace_name = 'TBS';
SEGMENT_NAME EXTENT_ID BLOCK_ID BYTES BLOCKS
------------ --------- -------- ------- ------
EMP 0 9 1048576 128
EMP 1 137 1048576 128
EMP 2 777 1048576 128
EMP 3 521 1048576 128
DEPT 0 265 1048576 128
DEPT 1 393 1048576 128
DEPT 2 905 1048576 128
SALGRADE 0 1033 1048576 128
SQL> SELECT *
FROM dba_free_space
WHERE tablespace_name = 'TBS':
TABLESPACE FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
---------- ------- -------- ------- ------ ------------
TBS 6 649 1048576 128 6
자동 확장은 분명 가능하지만 DROP TABLE이 진행되었던 영역 역시 빈 공간으로 인식하므로 해당 공간을 먼저 사용한 것을 확인 할 수 있다. 이렇게 이름만 변경해서 남겨져 있던 TEST 테이블의 공간이 사용되어 버리면 TEST 테이블은 복구 가능할까?
SQL> SELECT * FROM recyclebin;
no rows selected
RECYCLEBIN에 남겨진 정보가 없다. 당연히 FLASHBACK TABLE 명령도 진행 할 수 없다.
SQL> FLASHBACK TABLE test TO BEFORE DROP;
ERROR at line 1;
ORA-38305: object not in RECYCLE BIN
SQL> DROP TABLESPACE tbs INCLUDING CONTENTS AND DATAFILES;
Flashback Table 명령은 Drop 했던 테이블을 손 쉽게 복구 할 수 있는 기능 이외에도 Undo Data를 활용하여 보다 쉽게 이전 시점으로 Table을 되돌릴 수 있다.
SQL> CONN system/oracle
SQL> SELECT empno
, ename
, sal
, rowid
, DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) FNO
, DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) BNO
, DBMS_ROWID.ROWID_ROW_NUMBER(rowid) RNO
FROM emp
WHERE deptno = 10;
EMPNO ENAME SAL ROWID FNO BNO RNO
----- ------ ---- ----------------- --- --- ---
7782 CLARK 2450 AAAMfMAAEAAAAcAAG 4 28 6
7839 KING 5000 AAAMfMAAEAAAAcAAI 4 28 8
7934 MILLER 1300 AAAMfMAAEAAAAcAAN 4 28 13
현재 EMP 테이블의 10번 부서번호를 가지고 있는 행은 3개 존재하며, 4번 파일의 28번 Block 안에 6, 8, 13번 Row 위치에 저장되어 있는 것을 확인 할 수 있다.
SQL> SELECT SYSTIMESTAMP
, current_scn
FROM v$database;
SYSTEMSTAMP CURRENT_SCN
----------------------------------- -----------
20-APR-10 06:19:30:660541 AM +09:00 712492
Flashback Table 명령을 실행 시킬 때 사용할 현재 시간 및 SCN 확인 후 10번 부서 번호를 가지고 있는 몇몇 행 정보를 변경한다.
SQL> UPDATE emp SET sal = sal * 1.2 WHERE empno = 7782;
SQL> DELETE emp WHERE empno = 7839;
SQL> COMMIT;
DML 진행 후 COMMIT까지 수행 했으므로 ROLLBACK은 불가능한 상태이다. 하지만 앞에서 배운 Flashback Query 및 Version Query를 이용하면 이전 시점의 Data도 확인 가능하다..
SQL> SELECT empno
, ename
, sal
FROM emp AS OF TIMESTAMP (SYSDATE - INTERVAL '5' MINUTE)
WHERE deptno = 10;
EMPNO ENAME SAL
----- ------ ----
7782 CLARK 2450
7839 KING 5000
7934 MILLER 1300
SQL> SELECT empno
, ename
, sal
, versions_startscn AS startscn
, versions_endscn AS endscn
, versions_operation AS OP
FROM emp AS OF VERSION BETWEEN SCN MINVALUE AND MAXVALUE
WHERE deptno = 10;
일반적으로 DML 수행 시 시간 정보나 SCN을 확인하며, 작업을 진행하지는 않는다. 때문에 잘못 수행된 DML을 되돌리기 위해서 시간 정보 및 SCN 정보가 필요할 떄 Version Query는 매우 유용한 방법이 될 수 있다.
위의 결과는 SCN 712579부터 DELTE, UPDATE가 반영 되었다. VERSIONS_STARTTIME을 함께 검색하였다면 시간 정보도 얻을 수 있다.
잘못 수행 된 명령문이 있음을 확인 하였고 이미 COMMIT이 진행 된 이후 이므로 .ROLLBACK도 불가능한 상태이다. 하지만 Version Query를 이용하여 시점을 확인 하였다면 Flashback Table 명령을 이용하면 손 쉽게 복구 가능하다. 단, Flashback Table 명령을 통해 이전으로 되돌아 가려면 아래의 명령이 언제 수행되어야 한다.
SQL> ALTER TABLE emp ENABLE ROW MOVEMENT;
ROW MOVEMENT 명령을 수행 했다면 Flashback Table 명령을 수행해 보면,
SQL> FLASHBACK TABLE emp TO TIMESTAMP (SYSDATE - INTERVAL '10' MINUTE);
SQL> SELECT empno
, ename
, sal
, rowid
, DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) FNO
, DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) BNO
, DBMS_ROWID.ROWID_ROW_NUMBER(rowid) RNO
FROM emp
WHERE deptno = 10;
EMPNO ENAME SAL ROWID FNO BNO RNO
----- ------ ---- ----------------- --- --- ---
7782 CLARK 2450 AAAMfMAAEAAAAcAAG 4 29 6
7839 KING 5000 AAAMfMAAEAAAAcAAI 4 29 8
7934 MILLER 1300 AAAMfMAAEAAAAcAAN 4 29 13
UPDATE, DELETE가 진행되기 이전 상태로 되돌아 간 것을 확인 할 수 있다. 하지만 한가지 눈에 띄는 것은 ROWID이다. Flashback을 하기 전 확인 했던 ROWID는 28번 Block에 저장되어 있던 것이 29번 Block으로 옮겨져 있는 것을 확인 할 수 있다.
Flashback Table 명령은 이렇게 원래 저장되어 있는 주소가 아닌 새로운 Block으로 이전 또는 재 배치를 통해서 수행된다. 때문에 ROW MOVEMENT를 활성화 시켜야만 Flashback Table 명령을 수행 할 수 있게 된다.
참고: 테이블에 INSERT 된 각각의 행들은 다른 주소(ROWID)로 이동이 불가능 하다. 저장된 Row의 주소 값인 ROWID는 Index에서 pointer로 사용하기 위해 Index 안에 저장되어 있는 값이므로 각각의 Row들이 빈번하게 다른 주소로 이동하게 된다면 수 많은 Index에 추가적인 변경 작업이 진행 되어야 한다. 때문에 ROW MOVEMENT는 비활성화 되어 있다.
Flashback Table은 위와 같이 이전 시점으로 Table의 Data를 되돌릴 수 있다. 또한 특정 시간 및 SCN을 직접 지정하는 것도 가능하다.
여기서는 DML을 수행하기 전 미리 시간정보와 SCN 정보를 확인 해 두었기 때문에 해당 값으로 Flashback Table을 진행하는 것도 가능하다. 하지만 실제 업무에서는 이러한 시간 정보를 기록하며 작업하지 않으므로 Version Query를 이용하는 것도 좋은 방법이 된다. 단, VERSIONS_STARTSCN 또는 VERSIONS_STARTTIMESTAMP의 컬럼의 값을 그대로 사용하면 안 된다. 해당 컬럼의 값은 말 그대로 그 시점으로부터 DML이 반영 되었다는 것이므로 해당 값 보다 더 빠른 시간 및 더 낮은 SCN 값을 사용해야 한다.
SQL> FLASHBACK TABLE emo TO TIMESTAMP TO_TIMESTAMP ("20-APR-10 06:19:30:660541 AM");
미리 확인 해 두었던 시간 정보를 이용
SQL> FLASHBACK TABLE emo TO SCN 712578;
Version Query를 통해서 얻은 SCN 값 보다 1 작은 값을 이용
SQL> FLASHBACK TABLE emo TO SCN 712579;
DML이 반영 되었던 SCN 값을 이용하여 다시 DML의 결과를 반영
SQL> SELECT empno
, ename
, sal
, rowid
, DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) FNO
, DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) BNO
, DBMS_ROWID.ROWID_ROW_NUMBER(rowid) RNO
FROM emp
WHERE deptno = 10;
EMPNO ENAME SAL ROWID FNO BNO RNO
----- ------ ---- ----------------- --- --- ---
7782 CLARK 2450 AAAMfMAAEAAAAcAAG 4 29 19
7934 MILLER 1300 AAAMfMAAEAAAAcAAN 4 29 25
DML을 재 실행 한 것이 아니고 Flashback을 이용하여 다시 DELETE와 UPDATE 결과가 반영된 것을 확인 할 수 있다. 단, ROWID는 변경 된다.
SQL> FLASHBACK TABLE emo TO SCN 712578;
다시 원래대로 변경한다. 그렇다면 Flashback Table은 원하는 이전 시점 어디로든 되돌아 갈 수 있다.
SQL> FLASHBACK TABLE emo TO SCN 600000;
ERROR at line 1;
ORA-00604: error occured at recursive SQL level 1
ORA-12801: error signaled in parallel query server P000
ORA-01555: snapshot too old: rollback segment number 2 with name "_SYSSMU2$" too small
오래된 SCN을 이용하여 Flashback을 진행하면 Snapshot too old error가 발생한다. Flashback Table은 Undo Data를 이용하므로 접근하고자 하는 Undo Data가 존재하지 않으면 수행 할 수 없다.
SQL> SHOW PARAMETER UNDO_RETENTION
NAME TYPE VALUE
-------------- ------- -----
undo_retention integer 900
현재 설정된 parameter의 값은 900 초이다. 즉, 15분의 시간 동안은 COMMIT 된 Undo Data(ROLLBACK에 사용되지 못하는 이전 Data)를 읽기 일관성 및 Flashback 기술에 사용 가능하다. 하지만 900 초가 지나가면 Undo Data 들이 저장되어 있는 공간들은 재 사용되므로 접근이 불가능해 질 수 있다.
그밖에도 몇몇 제약들이 좀더 있으므로 보다 자세한 사항은 메뉴얼을 참고한다.
SQL> conn / as sysdba
SQL> alter database flashback on;
SQL> SELECT flashback_on FROM v$database;
FLASHBACK_ON
------------
YES
SQL> alter system switch logfile;
SQL> drop user scott cascade;
SQL> shutdown abort
SQL> startup mount
ORACLE instance started.
TotalSystem Global Area 481259520 bytes
Fixed Size 1337352 bytes
Variable Size 398460920 bytes
Database Buffers 75497472 bytes
Redo Buffers 5963776 bytes
Database mounted.
SQL> FLASHBACK DATABASE TO TIMESTAMP (SYSDATE - INTERVAL '10' MINUTE);
ERROR at line 1:
ORA-38729: Not enough flashback database log data to do FLASHBACK;
SQL> FLASHBACK DATABASE TO TIMESTAMP (SYSDATE - INTERVAL '5' MINUTE);
* ERROR 발생 시 RMAN에서 수행
[orcl:~]$ rman target /
RMAN> flashback database to timestamp (sysdate - interval '5' minute);
SQL> alter database open resetlogs;
SQL> select * from scott.dept;
DEPTNO DNAME LOC
------ ---------- --------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
[orcl:~]$ sqlplus / as sysdba
SQL> show parameter undo
NAME TYPE VALUE
--------------- ------- --------
undo_management string AUTO
undo_retention integer 1800
undo_tablespace string UNDOTBS1
SQL> create tablespace flash_tbs
datafile '/u01/app/oracle/oradata/orcl/flash_tbs.dbf' size 10m autoextend on;
SQL> create user archive_admin
identified by oracle
default tablespace flash_tbs;
SQL> grant connect, resource to achive_admin;
SQL> grant flashback archive administer to archive_admin;
SQL> conn archive_admin/oracle
SQL> create flashback archive FLA1
tablespace flash_tbs
retention 3 year;
SQL> grant flashback archive on FLA1 to scott;
SQL> conn scott/tiger
SQL> alter table scott.emp flashback archive FLA1;
SQL> alter table scott.dept flashback archive FLA1;
SQL> select owner_name, flashback_archive_name, retention_in_days
from user_flashback_archive;
OWNER_NAME FLASHBACK_ARCHIVE_NAME RETENTION_DAYS
------------- ---------------------- --------------
ARCHIVE_ADMIN FLA1 1095
SQL> select * from user_flashback_archive_tables;
TABLE_NAME OWNER_NAME FLASHBACK_ARCHIVE_NAME ARCHIVE_TABLE_NAME STATUS
---------- ---------- ---------------------- ------------------ -------
DEPT SCOTT FLA1 SYS_FBA_HIST_18872 ENABLED
EMP SCOTT FLA1 SYS_FBA_HIST_18873 ENABLED
SQL> select * from emp where deptno = 10;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ------ --------- ---- --------- ---- ---- ------
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7839 KING PRESIDENT 17-NOV-81 5000 10
7934 MILLER CLERK 7782 23-JAN-82 1300 10
SQL> update emp set sal = sal * 1.2 where deptno = 10;
SQL> commit;
SQL> select * from emp where deptno = 10;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ------ --------- ---- --------- ---- ---- ------
7782 CLARK MANAGER 7839 09-JUN-81 2940 10
7839 KING PRESIDENT 17-NOV-81 6000 10
7934 MILLER CLERK 7782 23-JAN-82 1560 10
SQL> select *
from emp as timestamp (sysdate - interval '1' hour)
where deptno = 10;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ------ --------- ---- --------- ---- ---- ------
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7839 KING PRESIDENT 17-NOV-81 5000 10
7934 MILLER CLERK 7782 23-JAN-82 1300 10
* 일정 시간이 흐른 뒤에 실행해도 검색 가능