본문 바로가기
카테고리 없음

[Flashback] Query, Version, Table, Archive, Database, Transaction

by jsyona 2026. 4. 21.
구분 대표 기능 Depends on 데이터 변경
Database Flashback DB Flashback Log O
Table Flashback Table Undo O
Table Flashback Drop Recycle Bin O
Query Flashback Query Undo X
Row 이력 Version Query Undo X
장기이력 Data Archive Undo+Archive O
Transaction Flashback Txn Undo+Redo O

 


Undo Retention Guarantee

Retention Guarantee 모드

alter tablespace undotbs1 retention guarantee;

모드가 켜지면 Undo retention 시간이 보장되고, 덮어쓰기되지 않는다.

대신 undo가 무한히 쌓일 수 없기 때문에, 공간이 부족하면 insert, update가 실패한다.

 

-- 모드 해제
alter tablespace undotbs1 retention noguarantee;

 

구분 NOGUARANTEE GUARANTEE
우선순위 Transaction 우선 Query 우선
Undo 부족 시 오래된 Undo 덮어씀 덮어쓰기 금지
결과 Query 실패 가능 Transaction 실패 가능
목적 일반 운영 Flashback 보장

Flashback이 반드시 필요한 상황에 Guarantee 모드를 사용한다.

일반적 상황에서는 트랜잭션이 실패될 수 있기 때문에 Noguarantee 모드를 사용한다.


파라미터 확인

undo_management = AUTO

오라클이 자동으로 undo를 관리한다.

undo_retention = 900

초 단위이므로 15분을 의미한다.

15분 동안 Undo를 보관한다.
undo_tablespace = UNDOTBS1


Flashback Query: 과거 시점 조회

select salary from hr.emp where employee_id = 100;

현재 시점 확인

select current_scn, systimestamp from v$database;

scn, timestamp를 확인한다.

update hr.emp set salary=salary*1.1 where employee_id=100;

-- 변경 확인
select salary from hr.emp where employee_id = 100;

commit;

undo에는 commit 전후 데이터가 모두 존재한다

Timestamp로 조회

select salary
from hr.emp
as of timestamp to_timestamp('2026-04-21 10.59.41', 'yyyy-mm-dd hh24:mi:ss')
where employee_id=100;

SCN으로 조회

select salary
from hr.emp
as of scn 4432774
where employee_id=100;


Flashback version query: versions_xid

초기 상태

drop table hr.emp purge;

create table hr.emp as select * from hr.employees;

현재 시점 확인

select current_scn, checkpoint_change#, systimestamp from v$database;

초기 데이터 상태

select employee_id, last_name, salary from hr.emp where employee_id in(110,111);

데이터 변경

update hr.emp set salary = 1000 where employee_id = 110;
delete from hr.emp where employee_id = 111;

select employee_id, last_name, salary from hr.emp where employee_id in(110,111);

commit;

timestamp 조회

select employee_id, last_name, salary
from hr.emp as of timestamp to_timestamp('2026-04-21 11.14.47','yyyy-mm-dd hh24:mi:ss')
where employee_id in(110,111);

EMPLOYEE_ID LAST_NAME           SALARY
----------- --------------- ----------
        110 Chen                  8200
        111 Sciarra               7700

timestamp 기간 조회

select versions_xid, employee_id, last_name, salary
from hr.emp
versions between timestamp
to_timestamp('2026-04-21 11:14:47','yyyy-mm-dd hh24:mi:ss')
and to_timestamp('2026-04-21 11:30:00','yyyy-mm-dd hh24:mi:ss')
where employee_id in(110,111);

VERSIONS_XID     EMPLOYEE_ID LAST_NAME           SALARY
---------------- ----------- --------------- ----------
07000B001D040000         111 Sciarra               7700
07000B001D040000         110 Chen                  1000
                         110 Chen                  8200
                         111 Sciarra               7700

Flashback Table: enable row movement

@database

      DBID DBNAME    OPEN_MODE            LOG_MODE     CHECKPOINT_CHANGE# CURRENT_SCN SYSTIMESTAMP
---------- --------- -------------------- ------------ ------------------ ----------- ---------------------------------------------------------------------------
1756186972 ORCL      READ WRITE           ARCHIVELOG              4429770     4434642 21-APR-26 11.38.57.590784 AM +09:00

 

delete from hr.emp;
commit;

select * from hr.emp;

Flashback Query로 복구

insert into hr.emp
select * from hr.emp 
as of timestamp to_timestamp('2026-04-21 11:38:57','yyyy-mm-dd hh24:mi:ss');

rollback;

select * from hr.emp;

rollback 시 복구된 것 초기화

Flashback Table 준비

alter table hr.emp enable row movement;

--확인
select row_movement 
from dba_tables 
where owner = 'HR' and table_name = 'EMP';

flashback table은 내부적으로 row 위치를 이동시키고, undo 기반으로 테이블을 재구성한다.

Flashback Table 실행

flashback table hr.emp to timestamp 
to_timestamp('2026-04-21 11:38:57','yyyy-mm-dd hh24:mi:ss');

--결과 확인
select count(*) from hr.emp;

자동으로 과거 상태로 복원한다.

이렇게 복구하면 이미 commit된 DDL처럼 취급되기 때문에 rollback으로 되돌릴 수 없다.

alter table hr.emp disable row movement;


Flashback Data Archive

undo는 retention이라는 한계가 있기 때문에 flashback archive로 장기 이력 저장

@datafile

     FILE# TBS_NAME   FILE_NAME                           CHECKPOINT_CHANGE# STATUS
---------- ---------- ----------------------------------- ------------------ -------
         1 SYSTEM     /u02/oradata/orcl/system01.dbf                 4429770 SYSTEM
         2 OETBS      /u02/oradata/orcl/oetbs01.dbf                  4429770 ONLINE
         3 SYSAUX     /u02/oradata/orcl/sysaux01.dbf                 4429770 ONLINE
         4 UNDOTBS1   /u02/oradata/orcl/undotbs01.dbf                4429770 ONLINE
         5 SHTBS      /u02/oradata/orcl/shtbs01.dbf                  4429770 ONLINE
         7 USERS      /u02/oradata/orcl/users01.dbf                  4429770 ONLINE
         8 OETBS      /u02/oradata/orcl/oetbs02.dbf                  4429770 ONLINE

Flashback 전용 Tablespace 생성

create tablespace fdatbs datafile '/u02/oradata/orcl/fdatbs01.dbf' size 50m autoextend on next 1m;

Flashback 이력 저장하기 위한 tablespace를 만든다.

  • 초기 크기: 50m
  • autoextend: 자동 확장
  • next 1m: 1mb씩 증가

Flashback Archive 생성

create flashback archive fda1 tablespace fdatbs quota 10m retention 1 year;

만든 tablespace에 flashback archive 생성

  • retention 1년
  • quota 10MB
select owner_name, flashback_archive_name, retention_in_days, create_time
from dba_flashback_archive;

OWNER_NAME FLASHBACK_ARCHIVE_NAME         RETENTION_IN_DAYS CREATE_TIME
---------- ------------------------------ ----------------- ---------------------------------------------------------------------------
SYS        FDA1                                         365 21-APR-26 11.52.13.000000000 AM

flashback archive 확인하는 쿼리이다.

테이블에 적용

 

alter table hr.emp flashback archive fda1;​

hr.emp 테이블에 flashback archive를 적용한다.

이후부터 테이블의 변경 이력이 fda1에 자동으로 저장된다

select table_name, owner_name, flashback_archive_name, archive_table_name, status
from dba_flashback_archive_tables;

TABLE_NAME OWNER_NAME FLASHBACK_ARCHIVE_NAME         ARCHIVE_TABLE_NAME             STATUS
---------- ---------- ------------------------------ ------------------------------ -------------
EMP        HR         FDA1                           SYS_FBA_HIST_75058             ENABLED

archive table 확인

데이터 변경

select employee_id, salary from hr.emp where department_id = 20;

EMPLOYEE_ID     SALARY
----------- ----------
        201      13000
        202       6000
        
update hr.emp set salary = 20000 where department_id = 20;

commit;

select employee_id, salary from hr.emp where department_id = 20;

EMPLOYEE_ID     SALARY
----------- ----------
        201      20000
        202      20000

이전 값 조회

select employee_id, salary from hr.emp as of timestamp(systimestamp-interval '5' minute)
where department_id = 20;

EMPLOYEE_ID     SALARY
----------- ----------
        201      13000
        202       6000

과거 상태를 조회한다.

Flashback Archive에 저장되므로, undo 없이도 과거 상태를 조회할 수 있다.

백그라운드 프로세스

! ps -ef | grep fbda | grep -v grep
oracle    2264     1  0 11:52 ?        00:00:00 ora_fbda_orcl

ora_fbda_orcl가 flashback data archive 관리하는 프로세스이다.

이 프로세스가 자동으로 이력을 저장하고 purge를 수행한다.

Flashback Archive 해제

alter table hr.emp no flashback archive;

select table_name, owner_name, flashback_archive_name, archive_table_name, status
from dba_flashback_archive_tables;

TABLE_NAME OWNER_NAME FLASHBACK_ARCHIVE_NAME         ARCHIVE_TABLE_NAME             STATUS
---------- ---------- ------------------------------ ------------------------------ -------------
EMP        HR         FDA1                           SYS_FBA_HIST_75058             DISABLED

disable 상태로 변경한다. 이력 저장이 중단된다.

retention 변경

select owner_name, flashback_archive_name, retention_in_days, create_time
from dba_flashback_archive;

OWNER_NAME FLASHBACK_ARCHIVE_NAME         RETENTION_IN_DAYS CREATE_TIME
---------- ------------------------------ ----------------- ---------------------------------------------------------------------------
SYS        FDA1                                         365 21-APR-26 11.52.13.000000000 AM

alter flashback archive fda1 modify retention 2 year;

select owner_name, flashback_archive_name, retention_in_days, create_time
from dba_flashback_archive;

OWNER_NAME FLASHBACK_ARCHIVE_NAME         RETENTION_IN_DAYS CREATE_TIME
---------- ------------------------------ ----------------- ---------------------------------------------------------------------------
SYS        FDA1                                         730 21-APR-26 11.52.13.000000000 AM

 

용량 변경

 

select * from dba_flashback_archive_ts;

FLASHBACK_ARCHIVE_NAME         FLASHBACK_ARCHIVE# TABLESPACE_NAME                QUOTA_IN_MB
------------------------------ ------------------ ------------------------------ ----------------------------------------
FDA1                                            1 FDATBS                         10

alter flashback archive fda1 modify tablespace fdatbs quota 20m;


select * from dba_flashback_archive_ts;

FLASHBACK_ARCHIVE_NAME         FLASHBACK_ARCHIVE# TABLESPACE_NAME                QUOTA_IN_MB
------------------------------ ------------------ ------------------------------ ----------------------------------------
FDA1                                            1 FDATBS                         20

purge

alter flashback archive fda1 purge before timestamp(systimestamp - interval '1' day);​

1일 이전 데이터를 삭제한다.

Archive 삭제

drop flashback archive fda1;

Flashback Archive 자체 제거

 


Flashback Database

데이터베이스 전체를 특정 시점으로 되감는 기능

@database

      DBID DBNAME    OPEN_MODE            LOG_MODE     CHECKPOINT_CHANGE# CURRENT_SCN SYSTIMESTAMP
---------- --------- -------------------- ------------ ------------------ ----------- ---------------------------------------------------------------------------
1756186972 ORCL      READ WRITE           ARCHIVELOG              4443653     4443914 21-APR-26 02.49.41.818260 PM +09:00

Flashback Database는 기본적으로 ARCHIVELOG 환경에서 사용해야 한다.

db가 로그를 보관하고 있어야 과거 시점으로 되돌릴 수 있다.

Flashback 보존 목표 시간 설정

alter system set db_flashback_retention_target=2880 scope=both;

show parameter db_flashback_retention_target

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_flashback_retention_target        integer     2880

2880분 = 48시간 = 2일

flashback log를 얼마나 오래 유지할지 목표 시간을 설정한다.

Flashback 기능 활성화

select flashback_on from v$database;

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

alter database flashback on;


select flashback_on from v$database;

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

현재 db에서 flashback database 기능이 켜져 있는지, 꺼져 있는지 확인한다.

꺼져 있다면 활성화시킨다.

FRA 설정 확인

show parameter db_recovery_file_dest

NAME                                 TYPE        VALUE
------------------------------------ ----------- --------------------------------
db_recovery_file_dest                string      /u02/oradata/fast_recovery_area                                                 a
db_recovery_file_dest_size           big integer 8256M

flashback log는 FRA에 저장된다.

FRA 경로가 현재 /u02/oradata/fast_recovery_area이다.

FRA 사용 현황

select * from v$flash_recovery_area_usage;

FILE_TYPE               PERCENT_SPACE_USED PERCENT_SPACE_RECLAIMABLE NUMBER_OF_FILES     CON_ID
----------------------- ------------------ ------------------------- --------------- ----------
CONTROL FILE                             0                         0               0          0
REDO LOG                                 0                         0               0          0
ARCHIVED LOG                             0                         0               0          0
BACKUP PIECE                         17.19                       .25               8          0
IMAGE COPY                               0                         0               0          0
FLASHBACK LOG                          .39                         0               2          0
FOREIGN ARCHIVED LOG                     0                         0               0          0
AUXILIARY DATAFILE COPY                  0                         0               0          0

flashback 기능이 생성한 로그가 flashback log 항목으로 확인된다.

Restore Point 생성

create restore point before_hr_emp_trunc;

select * from v$restore_point;

       SCN DATABASE_INCARNATION# GUA STORAGE_SIZE TIME                                     RESTORE_POINT_TIME   PRE NAME                 PDB CLE PDB_INCARNATION# REP     CON_ID
---------- --------------------- --- ------------ ---------------------------------------- -------------------- --- -------------------- --- --- ---------------- --- ----------
   4444063                     2 NO             0 21-APR-26 02.54.48.000000000 PM                               NO  BEFORE_HR_EMP_TRUNC  NO  NO                 0 NO           0

flashback database를 할 때 돌아갈 기준점을 before_hr_emp_trunc로 저장한다.

hr.emp truncate 하기 전 시점이라는 의미이다.

truncate

select count(*) from hr.emp;

  COUNT(*)
----------
       106

truncate table hr.emp;


select count(*) from hr.emp;

  COUNT(*)
----------
         0

truncate로 전체 데이터를 즉시 제거한다. 테이블 구조는 남지만, 데이터는 모두 사라진다.

복구하려면 flashback table, flashback database로 복구할 수 있다.

더보기

※drop table 한 경우

flashback table hr.emp to before drop;

mount

shut immediate

startup mount

 

flashback database는 mount 상태에서 주로 수행된다.

Flashback Database

flashback database to restore point before_hr_emp_trunc;

 

현재 DB 상태(truncate 후 상태)를 버리고 before_hr_emp_trunc 시점으로 돌린다.

hr.emp 테이블만 복구하는 게 아니라, 데이터베이스 전체를 해당 시점으로 돌아가게 된다.

read only로 열어서 확인

 

alter database open read only;

select count(*) from hr.emp;

  COUNT(*)
----------
       106

데이터가 원하는 상태로 돌아왔는지 안전하게 확인하기 위해서 read only로 db를 open한다.

mount

shut immediate

startup mount

open resetlogs

alter database open resetlogs;

select count(*) from hr.emp;

  COUNT(*)
----------
       106

flashback database는 과거 시점으로 db를 돌리기 때문에, 로그 시퀀스를 새로 시작해야 한다.

마무리

drop restore point before_hr_emp_trunc;

alter database flashback off;

restore point를 삭제하고 flashback 기능도 끈다.


Flashback Transaction

트랜잭션 단위 복구 기능이다.

이미 commit까지 끝난 DML이라도, 특정 트랜잭션 하나를 골라 되돌리는 작업이 가능하다.

rollback은 현재 세션에서 아직 commit되지 않은 작업만 취소하지만, flashback transaction backout은 이미 commit된 과거 트랜잭션도 되돌릴 수 있다.

기본 Supplemental Log 추가

alter database add supplemental log data;

Redo log에는 원래 복구에 필요한 최소 정보만 기록된다. 따라서 어떤 행이 바뀌었는지 추적하려면 정보가 부족하다.

 

이 명령으로 기본 supplemental log를 추가해서 redo에 변경 정보가 더 자세히 남도록 한다.

Primary Key 컬럼까지 추가 기록

alter database add supplemental log data (primary key) columns;

Primary Key 값도 redo에 남기도록 하는 설정

 

더보기

예를 들어, 아래처럼 급여를 바꿨다.

UPDATE employees SET salary = 24000 WHERE employee_id = 100;

이 쿼리에서 중요한 것은 where 조건의 행 식별 정보이다.

PK 컬럼까지 기록하게 하면, 어떤 행이 바뀌었는지 redo에 남게 된다.

Flashback 관련 권한 부여

grant execute on dbms_flashback to hr;
--flashback 관련 pl/sql

grant select any transaction to hr;
--트랜잭션 로그 조회 권한

DBMS_FLASHBACK 패키지 안의 프로시저를 실행할 수 있게 해주는 권한,

트랜잭션 로그 조회 권한을 부여한다.

잘못된 작업 수행

update employees set salary=50000;

commit;

employees 테이블의 salary를 전부 50000으로 바꿔버린 상황이다.

그리고 commit 했으므로 이제는 일반 rollback으로 되돌릴 수 없다.

트랜잭션 조회

select xid, operation, start_timestamp, commit_timestamp, logon_user, undo_sql
from flashback_transaction_query
where table_name='EMPLOYEES'
and table_owner='HR'
order by 3 desc


XID              OPERATION  START_TIMESTAMP    COMMIT_TIMESTAMP   LOGON_USER UNDO_SQL
---------------- ---------- ------------------ ------------------ ---------- ----------------------------------------------------------------------
0500020033040000 UPDATE     21-APR-26          21-APR-26          HR         update "HR"."EMPLOYEES" set "SALARY" = '8300' where ROWID = 'AAAR4CAAH
                                                                             AAAAGmAAI';

0500020033040000 UPDATE     21-APR-26          21-APR-26          HR         update "HR"."EMPLOYEES" set "SALARY" = '12008' where ROWID = 'AAAR4CAA
                                                                             HAAAAGmAAH';

0500020033040000 UPDATE     21-APR-26          21-APR-26          HR         update "HR"."EMPLOYEES" set "SALARY" = '10000' where ROWID = 'AAAR4CAA
                                                                             HAAAAGmAAG';

0500020033040000 UPDATE     21-APR-26          21-APR-26          HR         update "HR"."EMPLOYEES" set "SALARY" = '6500' where ROWID = 'AAAR4CAAH
                                                                             AAAAGmAAF';

XID              OPERATION  START_TIMESTAMP    COMMIT_TIMESTAMP   LOGON_USER UNDO_SQL
---------------- ---------- ------------------ ------------------ ---------- ----------------------------------------------------------------------

0500020033040000 UPDATE     21-APR-26          21-APR-26          HR         update "HR"."EMPLOYEES" set "SALARY" = '6000' where ROWID = 'AAAR4CAAH
                                                                             AAAAGmAAE';

0500020033040000 UPDATE     21-APR-26          21-APR-26          HR         update "HR"."EMPLOYEES" set "SALARY" = '13000' where ROWID = 'AAAR4CAA
                                                                             HAAAAGmAAD';

0500020033040000 UPDATE     21-APR-26          21-APR-26          HR         update "HR"."EMPLOYEES" set "SALARY" = '4400' where ROWID = 'AAAR4CAAH
                                                                             AAAAGmAAC';

0500020033040000 UPDATE     21-APR-26          21-APR-26          HR         update "HR"."EMPLOYEES" set "SALARY" = '2600' where ROWID = 'AAAR4CAAH

XID: 트랜잭션 ID

0500020033040000 -> salary를 50000으로 바꾼 트랜잭션 전체를 의미한다.

UNDO_SQL: 기존 값으로 되돌리는 SQL 쿼리를 보여준다.

 

ndo_sql을 107번 직접 복붙해서 실행해도 기존 값으로 복구할 수 있지만, 너무 비효율적이다.

따라서 XID를 이용해서 트랜잭션 단위로 복구하는 것이 편리하다.

Transaction Backout

begin
    dbms_flashback.transaction_backout(
        numtxns => 1,
        xids    => xid_array('0500020033040000'),
        options => dbms_flashback.nocascade
    );
end;
/

numtxns => 1: 되돌릴 트랜잭션 개수

xids => xid_array('0500020033040000')

: 해당 트랜잭션을 배열 형태로 넘긴다.

options => dbms_flashback.nocascade

: 해당 트랜잭션만 되돌리겠다는 의미이다. 관련된 다른 트랜잭션은 건들지 않는다.

(이 경우는 잘 수행되지만, 의존성이 있는 복잡한 트랜잭션에서는 실패할 수 있다.)

select salary from hr.employees;

    SALARY
----------
     24000
     17000
     17000
      9000
      6000
      4800
      4800
      4200
     12008
      9000

원래 값들로 복구되었다.