| 구분 | 대표 기능 | 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
원래 값들로 복구되었다.