
一部优秀的老电影中有这样一个经典的桥段,剧中角色打开月光宝盒大喊一声“波若波罗密”,便可触发时光倒流帮他回到事情发生之前以挽回悲剧结局,抑或直接回到500年前寻找他的前世姻缘。那么Oracle数据库中是否有类似的“宝物”,能帮我们嗖的一声回到“500年前”呢?让我们一起来探寻Oracle的月光宝盒--数据库闪回技术。
闪回技术的历史演进
基于undo的闪回
undo记录了每次数据变化中被覆盖的值,我们可以说它记录了数据变化时的前镜像值,例如一个事务将某数据从1改成了2,那么最终数据块记录的值应该是2,但是undo会记录下来更改前的值即1。undo数据是一个循环覆盖的结构,如下图:

基于undo的闪回我们主要介绍三种:闪回查询、闪回版本查询和闪回表。
闪回查询
闪回查询可以帮助我们查询一张表在过去某时间的数据状态。具体使用方法也很简单,主要就是在普通的select查询语句中多写一个“AS OF TIMESTAMP ”子句,以返回指定时间戳时的数据状态。
在我们日常使用时,主要有以下3种常用的方式:
-- 1.闪回到某精确时间点:SELECT * FROM <table_name> AS OF TIMESTAMPTO_TIMESTAMP('2020-12-21 08:45:00','yyyy-mm-dd hh24:mi:ss');-- 2.闪回到相对时间点之前(例如:1分钟前)SELECT * FORM <table_name AS OF TIMESTAMP SYSDATE - 1/24/60;-- 3.闪回到指定SCNSELECT * FROM <table_name> AS OF SCN 5572156;
闪回版本查询
使用VERSIONS子句查询某一段时间对应行的所有版本,返回结果是行的改变历史,且只返回已提交的行(包括删除和重新插入的行版本)。
SELECTversions_startscn,versions_starttime,versions_endscn,versions_endtime,versions_xid,versions_operation,last_name,salaryFROMemployeesVERSIONS BETWEEN TIMESTAMPTO_TIMESTAMP('2023-02-28 14:00:00', 'YYYY-MM-DD HH24:MI:SS')ANDTO_TIMESTAMP('2022-12-18 17:00:00', 'YYYY-MM-DD HH24:MI:SS')WHEREfirst_name = 'Steven';
| 标识列 | 含义 |
| VERSIONS_STARTSCN | 数据版本被创建时的SCN |
| VERSIONS_STARTTIME | 数据版本被创建时的时间戳 |
| VERSIONS_ENDSCN | 数据版本消逝时的SCN |
| VERSIONS_ENDTIME | 数据版本消逝时的时间戳 |
| VERSIONS_XID | 数据版本被创建时的事务号 |
| VERSIONS_OPERATION | 数据版本创建时的事务类型 |
闪回表闪回表技术可以将表恢复到过去的指定时间点,使用过程主要分为以下步骤和方式:
-- 1.开启行移动:ALTER TABLE <table_name> ENABLE ROW MOVEMENT;-- 2-1. 将表闪回到指定时间点FLASHBACK TABLE <table_name> TO TIMESTAMP TO_TIMESTAMP('2020-12-12 13:30:00','YYYY-MM-DD HH24:MI:SS');-- 2-2. 或将表闪回到 n分钟(小时)之前FLASHBACK TABLE <table_name> TO TIMESTAMP sysdate – N/24/60;-- 2-3. 将表闪回到指定的SCNFLASHBACK TABLE <table_name>TO SCN 5572156;
Flashback Data Archive(FDA)undo数据具有时效性,旧的undo数据会被新的事务产生的undo覆盖。所以,Oracle依赖于undo的闪回技术也会受到该时效性的影响,无法闪回到很久前的数据。
为了能够闪回到更久远的过去时刻,Oracle引入了FDA特性,即闪回数据归档,该特性最初在11g版本引入并被命名为Total Recall。它记录了数据库事务变化的历史值,将其固化在表空间中的闪回归档对象中保存,使开启了该功能的表可以不受undo覆盖限制,闪回到更远的历史时刻。

开启FDA示例:

基于回收站的闪回
Oracle数据库回收站是一个虚拟容器,所有丢弃的对象都驻留在其中。如果开启了回收站后,删除数据对象并不会立即释放该对象占用的空间,只有在满足一些条件的时候才会实际释放该对象占用的空间。例如表 EMP 是在 USERS 表空间中创建的,则删除的表 EMP 将保留在 USERS 表空间中。删除的表和任何关联对象(如索引、约束、嵌套表和其他依赖对象)都不会移动,它们只是用前缀 BIN$$ 重新命名该对象。可以通过数据字典视图:USER_RECYCLEBIN 和 DBA_RECYCLEBIN快速查看回收站中的对象。
Oracle的FLASHBACK DROP,可以逆转drop table操作,在数据没有purge的情况下将数据从回收站中恢复回来。
-- 闪回被drop的表FLASHBACK TABLE <table_name> TO BEFORE DROP;
基于闪回日志的数据库闪回
使用 Oracle 的闪回日志,将整个数据库恢复到特定时间点,可以闪回整个数据库或者单个PDB。闪回数据库需要依赖闪回日志,需要开启flashback database设置。
数据库闪回必须满足以下的前提条件:
然后需要以干净的方式停止数据库,并启动到mount状态:
SQL> shutdown immediateSQL> startup mount
通过以下命令可闪回到某指定的点(SCN,时间戳,日志序列号等):
FLASHBACK DATABASE TO TIMESTAMP TO_TIMESTAMP('2020-12-12 13:30:00','YYYY-MM-DD HH24:MI:SS');FLASHBACK DATABASE TO TIMESTAMP(sysdate - 2/24);FLASHBACK DATABASE TO SCN 9527;
闪回特性总结及适用场景
最后,我们以表格方式整理对比Oracle数据库的各项闪回技术,以及分别适合的应用场景。

闪回常见问题
编辑:萧宇





