Oracle闪回技术操作总结
一、闪回技术概述
1.1 什么是闪回技术
Oracle闪回技术(Oracle Flashback Technology)是一组Oracle数据库特性,允许用户查看数据库对象过去的状态,或将数据库对象恢复到以前的状态,而无需使用基于时间点的介质恢复。
从Oracle 9i版本开始,数据库引入了闪回查询的初步功能;到Oracle 10g,闪回技术得到了大幅扩展,甚至可以闪回整个数据库。Oracle 11g进一步引入了闪回数据归档(Flashback Data Archive),实现了"Oracle全面回忆(Total Recall)"功能。
1.2 闪回技术的核心价值
闪回技术最大的特点是能够有选择性地、高效地消除错误的影响,逆转人为错误。它主要用于应对以下场景:
- 用户误操作(误删除、误更新数据)
- 逻辑数据损坏
- 需要审计和追踪数据变更历史
- 快速恢复被删除的表
1.3 闪回技术的底层原理
闪回技术主要依赖两大核心机制:
| 机制 | 说明 |
|---|---|
| UNDO数据(撤销数据) | 记录事务修改前的旧值,用于闪回查询、闪回表、闪回版本查询和闪回事务查询 |
| 闪回日志(Flashback Log) | 记录数据块的变化前映像,用于闪回数据库 |
所有基于 UNDO 的闪回功能(闪回查询、闪回版本查询、闪回事务查询、闪回表)都依赖同一底层机制:UNDO 表空间中存储的事务前镜像(Before Image)数据。
当用户对数据执行 DML 操作(INSERT/UPDATE/DELETE)时,Oracle 会在修改数据之前,将数据的原始值写入 UNDO 表空间。这些前镜像数据就是闪回功能的"时间机器燃料"。闪回操作本质上是利用 UNDO 数据反向重放事务,将数据恢复到指定时间点的状态。
UNDO数据是持久的,即使在数据库关闭后仍然存在,其保留时间由undo_retention参数控制。
1.4 闪回技术分类
| 闪回功能 | 适用层级 | 依赖机制 | 引入版本 |
|---|---|---|---|
| 闪回数据库(Flashback Database) | 数据库/PDB级 | 闪回日志 | Oracle 10g |
| 闪回查询(Flashback Query) | 表/行级 | UNDO | Oracle 9i |
| 闪回表(Flashback Table) | 表级 | UNDO | Oracle 10g |
| 闪回版本查询(Flashback Version Query) | 行级 | UNDO | Oracle 10g |
| 闪回事务查询(Flashback Transaction Query) | 事务级 | UNDO | Oracle 10g |
| 闪回删除(Flashback Drop) | 表级 | 回收站 | Oracle 10g |
1.5 SCN 与 Timestamp 的选择
闪回操作支持两种时间定位方式:
| 方式 | 精度 | 适用场景 |
|---|---|---|
| SCN(系统改变号) | 精确到事务级别 | 多表关联恢复、需要严格一致性 |
| Timestamp(时间戳) | 约 3 秒误差 | 快速恢复、对精度要求不高 |
Oracle 内部使用 SCN 进行所有闪回操作。当使用 Timestamp 时,Oracle 会通过 SYS.SMON_SCN_TIME 表将时间映射为 SCN,该表每 5 分钟记录一次映射关系,仅保留最近约 5 天的数据,因此 Timestamp 方式存在最大约 3 秒的精度误差。
最佳实践:在执行关键批量操作前,先记录当前 SCN,以便精确恢复:
SELECT current_scn FROM v$database;
-- 使用 DBMS_FLASHBACK 包获取系统当前SCN
SELECT dbms_flashback.get_system_change_number FROM dual;
--时间和scn之间的转换
select timestamp_to_scn(to_timestamp('2026-08-15 09:11:35','yyyy-mm-dd hh24:mi:ss')) scn from dual;
二、闪回数据库(Flashback Database)
2.1 概述
闪回数据库可以将整个数据库或单个PDB回退到过去的某个时间点或SCN(系统改变号),是执行不完全数据库恢复的快速替代方案。它类似于数据库的"倒带"按钮,可以在用户对数据库造成逻辑数据损坏的情况下,将数据库恢复到正确的状态。
闪回数据库功能非常类似于RMAN的不完全恢复,但它依赖于闪回日志(Flashback Log)而非备份。
闪回数据库的使用场景:实际生产环境中,一般不会开启闪回数据库功能,很多时候只有在数据库进行版本升级、PSU、RU补丁包升级时,才会临时创建还原点,开启闪回功能,升级完毕后,就会关闭掉
2.2 闪回数据库的工作原理
启动闪回数据库时,数据库会将数据块的前映像保存在"闪回缓冲区"中,然后由恢复写入器(RVWR,Recovery Writer)后台进程将闪回缓冲区中的前映像数据保存到快速恢复区的闪回数据库日志中。
2.3 启用闪回数据库的前提条件
要使用闪回数据库,必须满足以下条件:
- 必须配置快速恢复区(Fast Recovery Area) :闪回日志只能保存在快速恢复区中
- 必须启用闪回模式 :执行
ALTER DATABASE FLASHBACK ON - 数据库必须运行在归档模式(ARCHIVELOG)
- 数据库必须处于MOUNT状态(不能是OPEN状态)
关键参数配置:
sql
-- 配置快速恢复区
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST = '/u01/app/oracle/fast_recovery_area' SCOPE=BOTH;
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 10G SCOPE=BOTH;
-- 启用闪回模式(数据库需处于MOUNT状态)
STARTUP MOUNT;
ALTER DATABASE FLASHBACK ON;
ALTER DATABASE OPEN;
2.4 查看闪回数据库信息
sql
-- 查看当前闪回状态
SELECT log_mode,flashback_on FROM v$database;
-- 查看闪回窗口范围(最早可闪回的SCN和时间)
SELECT oldest_flashback_scn, oldest_flashback_time FROM v$flashback_database_log;
-- 查看当前SCN
SELECT current_scn FROM v$database;
2.5 执行闪回数据库
sql
-- 1. 关闭数据库并启动到MOUNT状态
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
-- 2. 执行闪回数据库操作
-- 闪回到指定SCN
FLASHBACK DATABASE TO SCN 46963;
-- 闪回到指定时间戳
FLASHBACK DATABASE TO TIMESTAMP '2025-08-01 14:00:00';
-- 闪回到指定时间戳(使用TO_TIMESTAMP函数)
FLASHBACK DATABASE TO TIMESTAMP TO_TIMESTAMP('2025-08-01 14:00:00', 'YYYY-MM-DD HH24:MI:SS');
-- 3. 以只读方式打开数据库验证
ALTER DATABASE OPEN READ ONLY;
-- 4. 确认数据正确后,使用RESETLOGS打开
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE OPEN RESETLOGS;
案例
su - oracle
mkdir /oradata/orcl/fast_recovery_area
sqlplus "/as sysdba"
-- 配置快速恢复区
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST = '/oradata/orcl/fast_recovery_area' SCOPE=BOTH;
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 10G SCOPE=BOTH;
-- 启用闪回模式(数据库需处于MOUNT状态)
shutdown immediate;
STARTUP MOUNT;
ALTER DATABASE FLASHBACK ON;
ALTER DATABASE OPEN;
-- 查看当前闪回状态
SELECT log_mode,flashback_on FROM v$database;
-- 查看当前SCN,以此为本次案例闪回数据库的SCN值
SELECT current_scn FROM v$database;
SQL> SELECT current_scn FROM v$database;
CURRENT_SCN
-----------
1087066 --记录现有的scn值为1087066
--做一些操作,例如创建一个表
create table tab1 as select * from dba_users;
--停库启动到mount状态,准备闪回
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
-- 执行闪回数据库操作
-- 闪回到指定SCN
FLASHBACK DATABASE TO SCN 1087066; --闪回到记录的scn值
-- 以只读方式打开数据库验证
ALTER DATABASE OPEN READ ONLY;
SQL> select count(*) from tab1; --验证,做的一些操作,确实闪回掉了
select count(*) from tab1
*
ERROR at line 1:
ORA-00942: table or view does not exist
-- 确认数据正确后,使用RESETLOGS打开
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE OPEN RESETLOGS;
至此闪回完成!
2.6 闪回还原点
Restore point 有两种类型: Normal 和 Guaranteed
1) Normal restore point
创建语法: create restore point xxxxx;
**相当于某个时间点或者 SCN 的一个别名。 restore point 的名字和对应的 SCN 会保存在控制文件中。创建了 normal restore point 后,如果需要执行 **flashback database时,就可以指定目标时间点为该 restore point,而不需要指定当时的 SCN 了
2)Guaranteed restore point
创建语法:create restore point xxxx guarantee flashback database;
Guaranteed restore point 的功能和 normal restore point 的功能基本一致,也是作为SCN 的一个别名。但是它还有一些和 flashback database 相关的特性。前面也提到,在执行flashbackdatabase 到之前的某个时间点时,必须保证所需要的 flashback log 存在。
创建一个 guaranteed restore point,可以保证能将数据库 flashback 到该点,即使没有系统启用 flashback database **日志!**这是因为,在创建 guaranteed restore point 之后,对于任何 block 的第一次变更,都会将其前映象整个的记录下来。
如果系统启用了 flashback database 日志,那么 guaranteed restore point 可以保证能将数据库 flashback 到 guaranteed restore point 之后的任何时间点。一旦创建了可靠还原点,要密切关注 flashback_recovery_area 空间的使用情况,因为在创建guaranteed restore point 之后,对于任何 block 的第一次变更,都会将其前映象整个的记录下来。所以当不再使用某一可靠还原点后要及时删除;
使用案例:
SQL> SELECT log_mode,flashback_on FROM v$database;
LOG_MODE FLASHBACK_ON
------------ ------------------
ARCHIVELOG NO
SQL> create restore point res_point1 guarantee flashback database; --创建一个guarantee
Restore point created.
SQL> SELECT log_mode,flashback_on FROM v$database;
LOG_MODE FLASHBACK_ON
------------ ------------------
ARCHIVELOG RESTORE POINT ONLY --可以看到,数据库自动开启闪回
SQL> select name,scn,storage_size,guarantee_flashback_database from v$restore_point;
NAME SCN STORAGE_SIZE GUA
---------------------------------------- ---------- ------------ ---
RES_POINT1 1115280 52428800 YES
SQL> create table tab1 as select * from dba_users;
Table created.
SQL> select count(*) from tab1;
COUNT(*)
----------
31
SHUTDOWN abort;
STARTUP MOUNT;
SQL> flashback database to restore point res_point1; --执行闪回到还原点
Flashback complete.
SQL> ALTER DATABASE OPEN READ ONLY;
Database altered.
SQL> select count(*) from tab1 --验证,做的一些操作,确实闪回掉了
*
ERROR at line 1:
ORA-00942: table or view does not exist
启动数据库
SHUTDOWN IMMEDIATE;
ALTER DATABASE OPEN RESETLOGS;
SQL> drop restore point res_point1; --删除闪回点
Restore point dropped.
2.7 闪回数据库的注意事项
- 执行
FLASHBACK DATABASE后,必须使用ALTER DATABASE OPEN RESETLOGS才能获得写访问权限 - 控制文件不能是备份或重新创建的,否则所有闪回日志信息将被丢弃
- 闪回日志的保留时间由快速恢复区的大小和数据库活动量共同决定
- 闪回数据库操作不可逆,执行前建议先备份
- 实际生产环境,很少开启闪回数据库功能,基本只有数据库版本升级,PSU/RU补丁,需要升级数据字典时,才会临时开启!
三、闪回查询(Flashback Query)
3.1 概述
闪回查询允许用户查询过去某个时间点或某个SCN对应的表中的数据信息。它基于UNDO表空间中的回滚信息实现。通过闪回查询,可以在误删除或误更新数据后,轻松地检索丢失的数据。
闪回查询使用SELECT语句的AS OF子句来实现。
3.2 闪回查询的两种方式
| 方式 | 语法 | 说明 |
|---|---|---|
| 基于时间戳 | AS OF TIMESTAMP |
闪回到指定的时间点 |
| 基于SCN | AS OF SCN |
闪回到指定的SCN |
3.3 闪回查询示例
场景 :假设员工表employees中的数据在2025年8月1日14:00:00之后被误删除。
sql
-- 方式一:基于时间戳闪回查询
-- 查看2026年8月1日14:00:00时的数据
SELECT * FROM employees AS OF TIMESTAMP TO_TIMESTAMP('2026-08-01 14:00:00', 'YYYY-MM-DD HH24:MI:SS');
SELECT * FROM employees AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '1' HOUR); --查询1小时之前的数据
select * from employees as of timestamp (systimestamp - interval '120' second); ---查询120秒之前的数据
select * from employees as of timestamp (systimestamp - interval '2' minute); ---查询2分钟之前的数据
select * from employees as of timestamp (systimestamp - interval '12' hour); ---查询12小时之前的数据
select * from employees as of timestamp (systimestamp - interval '12' day); ---查询12天之前的数据
select * from employees as of timestamp sysdate-3; ---查询3天之前的数据
-- 方式二:基于SCN闪回查询
-- 先获取目标SCN(假设为1234567)
SELECT * FROM employees AS OF SCN 1234567;
3.4 使用 DBMS_FLASHBACK 包
DBMS_FLASHBACK 包提供了一种"时间机器"模式,进入闪回模式后,所有查询自动返回历史数据,无需在每条 SQL 中添加 AS OF 子句。适用于无法修改 SQL 代码的场景(如调用存储过程、使用第三方工具)。
-- 进入闪回模式(基于 SCN)
EXEC dbms_flashback.enable_at_system_change_number(14229608);
-- 进入闪回模式(基于时间)
EXEC dbms_flashback.enable_at_time(
TO_TIMESTAMP('2026-08-05 09:30:00', 'YYYY-MM-DD HH24:MI:SS')
);
-- 在闪回模式下执行普通查询(自动返回历史数据)
-- 注意:闪回模式下不能执行 DML 操作
SELECT * FROM hr.employees WHERE department_id = 50;
-- 退出闪回模式
EXEC dbms_flashback.disable;
案例:
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
1117700
SQL> delete from emp;
14 rows deleted.
SQL> select count(*) from emp;
COUNT(*)
----------
0
SQL> commit;
Commit complete.
SQL> EXEC dbms_flashback.enable_at_system_change_number(1117700);
PL/SQL procedure successfully completed.
SQL> select count(*) from emp; --可以看到自动进入闪回模式!
COUNT(*)
----------
14
SQL> delete from emp; --闪回模式下只能执行查询,不能执行 DML
delete from emp
*
ERROR at line 1:
ORA-08182: operation not supported while in Flashback mode
注意事项:
- 闪回模式下只能执行查询,不能执行 DML(INSERT/UPDATE/DELETE)。
- 必须先
DISABLE再重新ENABLE,不支持嵌套。 - 可以在闪回模式下打开游标存储结果集,退出闪回模式后再用结果集执行 DML。
3.4 注意事项
- 闪回查询的可用时间范围受
undo_retention参数限制 - 如果UNDO数据被覆盖,闪回查询将失败(ORA-01555:快照太旧)
- 不能对以下对象使用闪回查询:外部表、临时表、固定表(
V$视图) - 不能跨 DDL 操作闪回。如果在目标时间点之后执行了
ALTER TABLE ... DROP COLUMN、TRUNCATE TABLE、ALTER TABLE ... MOVE等修改表结构的 DDL,闪回查询会报错ORA-01466。 - Timestamp 方式存在最大约 3 秒的精度误差。
四、闪回表(Flashback Table)
4.1 概述
闪回表可以将一张或多张表恢复到特定的时间点,且整个过程不需要有备份。闪回表不仅恢复表中的数据,还会还原表及其关联的对象(如索引、约束条件、触发器)。
4.2 闪回表的原理
闪回表使用FLASHBACK TABLE语句从UNDO段中读取表的过去映像,并利用闪回查询重建表行。
4.3 闪回表的前提条件
执行闪回表操作需要满足以下条件:
-
权限要求:
- 拥有表的
FLASHBACK对象权限,或拥有FLASHBACK ANY TABLE系统权限 - 拥有表的
READ或SELECT权限 - 拥有表的
INSERT、DELETE和ALTER权限
- 拥有表的
-
行移动(Row Movement)必须启用:
sqlALTER TABLE table_name ENABLE ROW MOVEMENT;闪回表操作不保留ROWID,启用行移动允许Oracle在物理ROWID之间移动行
-
表不能跨越DDL操作:Oracle无法将表闪回到任何改变表结构的DDL操作之前
4.4 闪回表语法
sql
FLASHBACK TABLE [schema.]table_name
TO {SCN | TIMESTAMP} expr
[ENABLE | DISABLE] TRIGGERS;
4.5 闪回表示例
场景 :员工表emp中的数据在2026年8月1日14:00:00之后被误删除或误修改。
sql
-- 1. 启用行移动(必须先执行)
ALTER TABLE emp ENABLE ROW MOVEMENT;
-- 2. 查看当前SCN(建议记录,以备回退)
SELECT current_scn FROM v$database;
-- 3. 执行闪回表(基于时间戳)
FLASHBACK TABLE emp TO TIMESTAMP TO_TIMESTAMP('2026-08-01 14:00:00', 'YYYY-MM-DD HH24:MI:SS');
-- 或基于SCN
FLASHBACK TABLE emp TO SCN 1234567;
-- 4. 验证恢复结果
SELECT * FROM emp;
案例:
SQL> create table emp as select * from scott.emp;
Table created.
SQL> SELECT current_scn FROM v$database;
CURRENT_SCN
-----------
1116547
SQL> delete from emp;
14 rows deleted.
SQL> commit;
Commit complete.
SQL> alter table emp enable row movement;
Table altered.
SQL> FLASHBACK TABLE emp TO TIMESTAMP TO_TIMESTAMP('2026-08-06 10:06:00', 'YYYY-MM-DD HH24:MI:SS');
Flashback complete.
SQL> select count(*) from emp;
COUNT(*)
----------
14
SQL> delete from emp;
14 rows deleted.
SQL> commit;
Commit complete.
SQL> FLASHBACK TABLE emp TO scn 1116547;
Flashback complete.
SQL> select count(*) from emp;
COUNT(*)
----------
14
4.6 闪回多张表
sql
-- 一次性闪回多张表(所有表要么全部成功,要么全部失败)
FLASHBACK TABLE emp, dept, salgrade
TO TIMESTAMP TO_TIMESTAMP('2025-06-01 14:00:00', 'YYYY-MM-DD HH24:MI:SS');
案例
SQL> create table dept as select * from scott.dept;
Table created.
SQL> SELECT current_scn FROM v$database;
CURRENT_SCN
-----------
1116633
SQL> select count(*) from emp;
COUNT(*)
----------
14
SQL> delete from emp;
14 rows deleted.
SQL> select count(*) from dept;
COUNT(*)
----------
4
SQL> delete from dept;
4 rows deleted.
SQL> commit;
Commit complete.
SQL> select count(*) from emp;
COUNT(*)
----------
0
SQL> select count(*) from dept;
COUNT(*)
----------
0
SQL> alter table dept enable row movement;
Table altered.
SQL> flashback table emp,dept to scn 1116633;
Flashback complete.
SQL> select count(*) from emp;
COUNT(*)
----------
14
SQL> select count(*) from dept;
COUNT(*)
----------
4
4.7 注意事项
- 闪回表操作在单个事务中执行,要么全部成功,要么全部失败
- 闪回表操作会获取表的独占DML锁,阻止操作期间对表的任何操作
- 闪回表操作不可回滚
- 闪回表操作建议先记录当前SCN,以便需要时可以再次闪回到当前时间
- 默认情况下,闪回表操作会自动禁用表上的所有触发器,操作完成后再自动重新启用。这是为了防止闪回过程中触发器被意外触发导致级联影响
- 不能闪回以下对象:簇表(Cluster Table)、物化视图(Materialized View)、高级队列表(AQ Table)、远程表(通过 DB Link 访问)。
- 不能跨越修改表结构的 DDL :如
DROP COLUMN、DROP PARTITION、TRUNCATE TABLE、MOVE TABLE等操作会导致 UNDO 数据失效,闪回表会报错ORA-01466。 SYS用户的表不能执行闪回表操作。
五、闪回版本查询(Flashback Version Query)
5.1 概述
闪回版本查询可以获取在给定的时间区间内指定行的不同版本。每当执行COMMIT语句时,一个新的行版本将被创建。这个功能提供了一个审计行改变的查询能力,通过它可以查找到所有已经提交的行记录。
闪回版本查询使用SELECT语句的VERSIONS BETWEEN子句来指定时间区间。
5.2 语法格式
sql
SELECT columns
FROM table_name
VERSIONS BETWEEN {SCN | TIMESTAMP} {expr | MINVALUE} AND {expr | MAXVALUE}
[AS OF {SCN | TIMESTAMP} expr]
[WHERE condition];
5.3 闪回版本查询的伪列
闪回版本查询提供了以下伪列(Pseudocolumns),用于获取每个版本的详细信息:
| 伪列 | 说明 |
|---|---|
VERSIONS_STARTSCN |
当前版本开始的SCN |
VERSIONS_STARTTIME |
当前版本开始的时间 |
VERSIONS_ENDSCN |
当前版本结束的SCN |
VERSIONS_ENDTIME |
当前版本结束的时间,一般就是下面一条记录开始的时间 |
VERSIONS_XID |
创建该版本的事务ID |
VERSIONS_OPERATION |
操作类型(I=INSERT, U=UPDATE, D=DELETE) |
5.4 闪回版本查询案例
sql
-- 1. 创建测试表并插入数据
CREATE TABLE flashback_test (id NUMBER, name VARCHAR2(20));
INSERT INTO flashback_test VALUES (1, 'Tom'); COMMIT;
INSERT INTO flashback_test VALUES (2, 'Mary'); COMMIT;
INSERT INTO flashback_test VALUES (3, 'Mike'); COMMIT;
UPDATE flashback_test SET name = 'Mary123' WHERE id = 2; COMMIT;
-- 2. 查询表上所有历史版本
SELECT * FROM flashback_test
VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
-- 3. 查看每个版本的详细信息(含伪列)
set linesize 200 pagesize 999
col name format a10
SELECT id, name,
to_char(versions_starttime,'yyyymmdd hh24:mi:ss') as v_start,
to_char(versions_endtime,'yyyymmdd hh24:mi:ss') as v_end,
VERSIONS_STARTSCN,
VERSIONS_ENDSCN,
versions_operation,
versions_xid
FROM flashback_test
VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
ORDER BY id, versions_starttime;
-- 输出示例:
ID NAME V_START V_END VERSIONS_STARTSCN VERSIONS_ENDSCN V VERSIONS_XID
---------- ---------- ---------------- ---------------- ----------------- --------------- - ----------------
1 Tom 20260806 10:12:39 1116980 I 2200060014000000
2 Mary123 20260806 10:12:39 1116987 U 2700170014000000
2 Mary 20260806 10:12:39 20260806 10:1239 1116982 1116987 I 25001F0013000000
3 Mike 20260806 10:12:39 1116984 I 2400000017000000
从上述结果,可以看到,"2 Mary" 行的结束scn 1116987 ,就是行"2 Mary123"开始的scn号值!
5.5 指定时间区间的版本查询
sql
-- 基于时间戳区间
SELECT * FROM flashback_test
VERSIONS BETWEEN TIMESTAMP
TO_TIMESTAMP('20260806 10:12:35', 'YYYY-MM-DD HH24:MI:SS')
AND TO_TIMESTAMP('20260806 10:13:39', 'YYYY-MM-DD HH24:MI:SS')
WHERE id = 1;
-- 基于SCN区间
SELECT * FROM flashback_test
VERSIONS BETWEEN SCN 1116980 AND 1116987
WHERE id = 1;
5.6 注意事项
- 闪回版本查询基于UNDO数据,因此可查询的时间范围受
undo_retention限制 - Oracle建议避免在
VERSIONS查询中使用versions_starttime、versions_endtime或scn_to_timestamp列,以提升性能 VERSIONS子句不能跨越修改了表结构的 DDL 语句。
六、闪回事务查询(Flashback Transaction Query)
6.1 概述
闪回事务查询实际上是对闪回版本查询的一个扩充,通过它可以审计某个事务甚至撤销一个已经提交的事务。它是一种诊断工具,可以用来查看在事务处理级别对数据库所做的更改。
闪回事务查询的核心是使用FLASHBACK_TRANSACTION_QUERY视图来确定所有必要的SQL语句,这些语句可以用来还原特定事务处理或特定时间段内所做的修改。
6.2 FLASHBACK_TRANSACTION_QUERY视图结构
sql
DESC flashback_transaction_query;
| 列名 | 说明 |
|---|---|
XID |
事务ID(RAW类型) |
START_SCN |
事务开始的SCN |
START_TIMESTAMP |
事务开始的时间 |
COMMIT_SCN |
事务提交的SCN |
COMMIT_TIMESTAMP |
事务提交的时间 |
LOGON_USER |
登录用户 |
UNDO_CHANGE# |
UNDO变更号 |
OPERATION |
操作类型 |
TABLE_NAME |
表名 |
TABLE_OWNER |
表所有者 |
ROW_ID |
行ID |
UNDO_SQL |
用于撤销该操作的SQL语句 |
6.3 闪回事务查询的前提条件
sql
-- 授予查询事务的权限
GRANT SELECT ANY TRANSACTION TO username;
-- 启用补充日志(Supplemental Logging)
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;
6.4 闪回事务查询案例
场景:撤销一个已提交的事务。
sql
-- 启用补充日志(Supplemental Logging)
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;
SQL> delete flashback_test where id=1;
1 row deleted.
SQL> commit;
Commit complete.
SELECT id, name, versions_operation, versions_xid
FROM flashback_test
VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
ID NAME V VERSIONS_XID
---------- ---------- - ----------------
1 Tom D 2400210016000000 --获取这个事务的undo语句
2 Mary123 U 2700170014000000
3 Mike I 2400000017000000
2 Mary I 25001F0013000000
1 Tom I 2200060014000000
SELECT xid, operation, start_scn, commit_scn, logon_user, undo_sql
FROM flashback_transaction_query
WHERE xid = HEXTORAW('2400210016000000');
XID OPERATION START_SCN COMMIT_SCN LOGON_USER
---------------- -------------------------------- ---------- ---------- ------------------------------
UNDO_SQL
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2400210016000000 DELETE 1117284 1117286 USER1
insert into "USER1"."FLASHBACK_TEST"("ID","NAME") values ('1','Tom'); --可以看到已经获取到!
2400210016000000 BEGIN 1117284 1117286 USER1
6.5 闪回事务(Flashback Transaction)--- 自动撤销事务
Oracle 11g 引入了 DBMS_FLASHBACK.TRANSACTION_BACKOUT 存储过程,可以自动撤销指定事务,无需手动执行 UNDO_SQL。
-- 撤销单个事务
DECLARE
xids XID_ARRAY;
BEGIN
xids := XID_ARRAY(HEXTORAW('2700060015000000'));
DBMS_FLASHBACK.TRANSACTION_BACKOUT(
numtxns => 1,
xids => xids,
options => DBMS_FLASHBACK.CASCADE
);
END;
/
options 参数说明:
| 选项 | 含义 |
|---|---|
CASCADE |
递归撤销目标事务及其所有依赖的子事务 |
NOCASCADE |
仅撤销目标事务,如果有依赖事务则报错(默认值) |
NOCASCADE_FORCE |
仅撤销目标事务,忽略依赖关系 |
NONCONFLICT_ONLY |
仅撤销不与当前数据冲突的操作 |
6.6 注意事项
- 闪回事务查询基于UNDO数据,可用时间范围受
undo_retention限制 - 必须启用补充日志才能捕获足够的信息用于事务撤销
- Oracle 11g引入了
FLASHBACK TRANSACTION命令,在底层使用闪回事务查询来简化事务回退操作
七、闪回删除(Flashback Drop)
7.1 概述
闪回删除可以从Oracle数据库的回收站中将已删除的对象恢复到删除之前的状态。它可以撤销DROP TABLE语句产生的影响,而不需要借助于传统的时间点恢复。
闪回删除比时间点恢复等其他恢复机制快得多 ,并且不会导致停机或丢失最近的事务。
7.2 回收站(Recycle Bin)的工作原理
回收站是所有被删除对象及其相依对象的逻辑存储容器。当删除一个表时,该表及其依赖的对象并不会马上被数据库彻底删除,而是被保存到回收站中。
| 特性 | 说明 |
|---|---|
| 重命名 | 删除后,表被重命名为系统生成的唯一名称(格式:BIN$globalUID$version) |
| 空间管理 | 表空间空间不足时,Oracle可能会自动清理回收站中的内容以释放空间 |
| 依赖对象 | 索引、触发器、约束等依赖对象一起进入回收站 |
7.3 启用/查看回收站
sql
-- 查看回收站是否启用
SELECT value FROM v$parameter WHERE name = 'recyclebin';
-- 启用回收站(默认启用)
ALTER SYSTEM SET recyclebin = ON;
-- 禁用回收站(不建议)
ALTER SYSTEM SET recyclebin = OFF;
7.4 查看回收站内容
sql
-- 查看当前用户的回收站
SHOW RECYCLEBIN;
-- 或使用SQL查询
SELECT original_name, object_name, type, droptime
FROM recyclebin;
-- 查看所有用户的回收站(需要DBA权限)
SELECT owner, original_name, object_name, type, droptime
FROM dba_recyclebin;
7.5 闪回删除案例
sql
-- 1. 删除员工表(不指定PURGE)
DROP TABLE emp;
-- 2. 查看回收站确认表已被删除
SHOW RECYCLEBIN;
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
EMP BIN$WFiu6/pVJYDgZSaPOUOczg==$0 TABLE 2026-08-06:10:31:20
-- 3. 使用原表名闪回删除(恢复最近删除的同名表)
FLASHBACK TABLE emp TO BEFORE DROP;
-- 4. 验证恢复
SELECT * FROM emp;
-- 5. 如果存在多个同名表,使用回收站中的唯一名称恢复
FLASHBACK TABLE "BIN$2wRA2DnkHfrgUwEAAH88+w==$0" TO BEFORE DROP;
-- 6. 恢复时重命名
FLASHBACK TABLE emp TO BEFORE DROP RENAME TO emp_old;
7.6 清空回收站
sql
-- 清空当前用户的回收站
PURGE RECYCLEBIN;
-- 清空指定表空间中的回收站
PURGE TABLESPACE users;
-- 清空所有用户的回收站(需要DBA权限)
PURGE DBA_RECYCLEBIN;
7.7 闪回删除的限制
| 限制 | 说明 |
|---|---|
| TRUNCATE操作 | TRUNCATE TABLE无法通过闪回删除恢复 |
| PURGE选项 | DROP TABLE ... PURGE不会进入回收站 |
| SYSTEM表空间 | 存储在SYSTEM表空间中的表不支持闪回删除 |
| 级联删除 | DROP USER ... CASCADE删除的用户表无法闪回 |
| 空间压力 | 表空间空间不足时,Oracle可能自动清理回收站 |
7.8 闪回删除的权限要求
- 任何拥有对象
DROP权限的用户都可以删除对象并将其放入回收站 FLASHBACK TABLE ... TO BEFORE DROP的权限与DROP权限绑定- 清空回收站的权限与
DROP权限绑定
八、闪回功能对比与选择指南
8.1 各闪回功能对比
| 功能 | 恢复粒度 | 依赖机制 | 是否需停机 | 适用场景 |
|---|---|---|---|---|
| 闪回数据库 | 整个数据库/PDB | 闪回日志 | 需要(MOUNT状态) | 大面积逻辑损坏 |
| 闪回查询 | 查询结果 | UNDO | 否 | 查看历史数据、审计 |
| 闪回表 | 单表/多表 | UNDO | 否(有锁) | 表数据误操作 |
| 闪回版本查询 | 行版本 | UNDO | 否 | 审计行变更历史 |
| 闪回事务查询 | 事务 | UNDO+补充日志 | 否 | 撤销特定事务 |
| 闪回删除 | 被DROP的表 | 回收站 | 否 | 误删除表恢复 |
九、常见问题与注意事项
9.1 ORA-01555:快照太旧(Snapshot Too Old)
原因:查询所需的UNDO数据已被覆盖。
解决方法:
- 增加
undo_retention参数值 - 扩大UNDO表空间
- 优化长查询,减少查询时间
9.2 闪回数据库无法闪回到目标时间
原因:闪回日志已被覆盖或快速恢复区空间不足。
解决方法:
- 增加快速恢复区大小
- 检查
v$flashback_database_log确认闪回窗口范围
9.3 闪回表失败
可能原因:
- 未启用行移动(Row Movement)
- 表在目标时间点之后执行过DDL操作
- UNDO数据不足
9.4 闪回删除的表无法恢复
可能原因:
- 使用了
PURGE选项删除 - 回收站已被清空
- 表空间空间不足导致回收站被自动清理