而Flashback Table 能直接将表里的数据rollback到历史上的某个时间点. 如果rollback 到用户误删除数据之前的时间点, 则回把误删除的数据行恢复. 在这个过程中, 数据库仍然是在线可用的.
Flashback Table 也是利用undo 表空间的旧数据. 假如所需的undo数据由于保留的时间超过了初始化参数undo_retention所指定的值. 从而被其他事务覆盖掉的话, 就有可能恢复失败.
Flashback table 操作会修改表里的数据, 从而有可能引起data rows的行移动, 比如某一行datarow当前在A block中, 而在表闪回到以前的某个时间点上市, 在那个时间点那个 datarow 在B block中, 那么在执行Flashback table 前必须启用数据行的移动特性.
Alter table <table_name> enable row movement;
Oracle 11g Flashback table 的特性:
1、在线操作;
2、恢复到指定时间点或 SCN 或 储存点(restore point)的任何数据;
3、自动恢复相关属性、如索引、触发器等(但是删除的索引, trigger不能通过flashback table来恢复)
4、满足分布式的一致性;
5、满足数据一致性,所有相关对象将自动一致;
6、闪回表技术是基于回滚数据(undo data)来实现的,因此,要想闪回表到过去的某
个时间上,必须确保与回滚表空间有关的参数设置合理。
语法:
Flashback table <table_name> to SCN <scn_number> [<ENABLE|DISABLE> TRIGGERS]
Flashback table <table_name> to Timestamp <scn_number> [<ENABLE|DISABLE> TRIGGERS]
注意的是, Flashback Table 可以向前Flashback, 一旦执行向前Flashback 后也可以执行向后flashback. 而 Sys schema下的table不能执行Flashback table操作.
6.1 Flashback table 的一些特性和注意事项Flashback table 命令作为单独的1个事务执行, 获取DML锁, 统计信息不会被闪回; 当前的索引和依赖对象会被维护.
具有如下特性:
1. 不能对系统表执行flashback table 操作. sys schema下的表不支持flashback table.
2.在执行DDL操作后不能执行向前的flashback 操作. (例如增删数据列, 增加约束)
3. Flashback table 操作会被写入alert 日志文件.
4. Flashback table 操作会产生undo 和 redo 数据.
5. flashback query 对 v$tables,x$tables 等动态性能视图无效,不过对于dba_*,all_*,user_*等数据字典是有效的
6. 执行delete(不是drop)的操作的表也可以被flashback table 恢复, 但是被truncate 操作的表是不能被flashback table恢复的. 因为它使用undo数据.
基于undo的表恢复, flashback table 实际上做的也是dml操作(会在被操作的表上加上dml锁), 因此还需注意triggers的影响.
此时可以在后面附加 ENABLE | DISABLE TRIGGERS 字句来handle.
6.2 Flashback table 的例子: 6.2.1 基于TIMESTAMP 的FlashBack1. 首先创建两张相同内容的表t1 和 t2
SQL> drop table t2;
Table dropped.
SQL> create table t1 as select * from user_objects;
Table created.
SQL> create table t2 as select * from t1;
Table created.
SQL> select sysdate from dual;
SYSDATE
-------------------
2014-05-25 12:10:50
2. 为表t1 创建两个indexes
SQL> create index idx1_t1 on t1(object_name);
Index created.
SQL> create index idx2_t1 on t1(object_id);
Index created.
SQL> select sysdate from dual;
SYSDATE
-------------------
2014-05-25 12:14:30
3.删除1个index, 删除其中t1所有数据行, truncate t2.
SQL> drop index idx1_t1;
Index dropped.
SQL> delete from t1;
11 rows deleted.
SQL> commit;
Commit complete.
SQL> truncate table t2;
Table truncated.
SQL> select sysdate from dual;
SYSDATE
-------------------
2014-05-25 12:16:52
4. 查看row movement状态并启用 t1 和 t2的 row movement 属性.
SQL> select table_name, row_movement from user_tables where table_name in ('T1','T2');
TABLE_NAME ROW_MOVE
------------------------------ --------
T1 DISABLED
T2 DISABLED
SQL> alter table t1 enable row movement;
Table altered.
SQL> alter table t2 enable row movement;
Table altered.
SQL> select table_name, row_movement from user_tables where table_name in ('T1','T2');
TABLE_NAME ROW_MOVE
------------------------------ --------
T1 ENABLED
T2 ENABLED
5. 对t1 执行flashback操作, 可以看到所有被删除的数据行都被恢复了, 但是drop掉的索引无法恢复.
SQL> flashback table t1 to timestamp to_timestamp('2014-05-25 12:13:00','yyyy-mm-dd hh24:mi:ss');
Flashback complete.
SQL> select count(1) from t1;
COUNT(1)
----------
11
SQL> select index_name, table_name from user_indexes;
INDEX_NAME TABLE_NAME
------------------------------ ------------------------------
IDX2_T1 T1
6. 尝试flashback table for t2 失败, 因为被truncate 的表无法通过flashback table 恢复.
SQL> flashback table t2 to timestamp to_timestamp('2014-05-25 12:14:00','yyyy-mm-dd hh24:mi:ss');
flashback table t2 to timestamp to_timestamp('2014-05-25 12:14:00','yyyy-mm-dd hh24:mi:ss')
*
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed
SQL> select count(1) from t2;
COUNT(1)
----------
0
1. 下面我创建3个restore point, 分别对应插入3条数据行到表test3.
SQL> select * from test3;
ID NAME
---------- ----------
1 Jack
2 Calvin
4 Paula
4 Paula
SQL> create restore point zero;
Restore point created.
SQL> insert into test3 select 5,'Alice' from dual;
1 row created.
SQL> commit;
Commit complete.
SQL> create restore point one;
Restore point created.
SQL> insert into test3 select 6,'Hebe' from dual;
1 row created.
SQL> commit;
Commit complete.
SQL> create restore point two;
Restore point created.
SQL> insert into test3 select 7, 'Ella' from dual;
1 row created.
SQL> commit;
Commit complete.
SQL> select * from test3;
ID NAME
---------- ----------
1 Jack
2 Calvin
4 Paula
4 Paula
7 Ella
5 Alice
6 Hebe
7 rows selected.
2. 对test3 执行恢复到restore point two, 在其后插入的数据行7, Ella 没有恢复.
SQL> alter table test3 enable row movement;
Table altered.
SQL> flashback table test3 to restore point two;
Flashback complete.
SQL> select * from test3;
ID NAME
---------- ----------
1 Jack
2 Calvin
4 Paula
4 Paula
5 Alice
6 Hebe
6 rows selected.
SQL> drop restore point one;
Restore point dropped.
SQL> drop restore point zero;
Restore point dropped.
SQL> drop restore point two;
Restore point dropped.
6.2.3 对于具有fk约束关系的两个表一同恢复.1, 创建两张表t3, t4,
SQL> create table t3 enable row movement as select * from scott.emp;
Table created.
SQL> create table t4 enable row movement as select * from scott.dept;
Table created.
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
3108694
2. 为这两张表添加pk 及 fk约束.
SQL> alter table t3 add constraint t3_empno_pk primary key(empno);
Table altered.
SQL> alter table t4 add constraint t4_deptno_pk primary key(deptno);
Table altered.
SQL> alter table t3 add constraint t3_t4_deptno_fk foreign key(deptno) references t4(deptno);
Table altered.
3. 对应先后删除t3 和 t4 部门号码是20的数据.
SQL> select empno, deptno from t3 where deptno = 10;
EMPNO DEPTNO
---------- ----------
7782 10
7839 10
7934 10
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
3109085
SQL> delete from t3 where deptno = 10;
3 rows deleted.
SQL> delete from t4 where deptno = 10;
1 row deleted.
SQL> commit;
Commit complete.
4. 尝试单独恢复t3 到数据删除前, get到error, 因为约束关系(当前t4不存在部门号码=20)的数据.
SQL> flashback table t3 to scn 3109085;
flashback table t3 to scn 3109085
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02291: integrity constraint (BILL.T3_T4_DEPTNO_FK) violated - parent key
not found
5. t3, t4 一起恢复就ok了!
SQL> flashback table t3,t4 to scn 3109085;
Flashback complete.
6.检查数据, 部门号码为20的数据已被恢复:
SQL> select t3.empno, t4.deptno from t3, t4 where t4.deptno = t3.deptno and t4.deptno = 10;
EMPNO DEPTNO
---------- ----------
7782 10
7839 10
7934 10
通过上面的介绍以及例子, 相信大家都知道flashback table 能恢复被删除/or 被修改的数据行.
但是不能恢复被drop掉的index, 更别说恢复被drop掉的表了.
如果想恢复被drop掉的对象. oracle提供另1个flashback成员, 就是Flashback drop.
语法:
跟上面的Flashback table 很类似, 只不过to后面不再是scn or timestamp, 而是 before drop
Flashback table <table_name> to before drop;
在没有flashback技术之前, 如果想恢复用户唔删除的表和对象. 只能使用传统的数据恢复方式从备份中恢复.
有了flashback 之后, 当用户使用drop table删除一张表时, 该表并不会在数据库中立即删除, 而是保持原表的位置. 但是将删除的表重新命名, 并将删除的表的信息存储在回收站中, 回收占记录了被删除的表的新名字和旧名字. 显然此时被删除的表所占的空间没有被立即释放, 变成数据库可以使用的潜在空间. 记录在回收站的信息会保留一段时间, 知道回收站空间不足或使用purge指令删除回收站中的记录.
回收站是1个逻辑结构, 不具有物理数据结构, 只要删除的表信息记录在回收站, 就可以通过flashback 来恢复被drop的表. 每个表空间都有1个叫做回收站(recyclebin)的逻辑区域.
也就是讲: 跟上面flashback成员不同, drop掉的表or其他对象, 并没有undo数据被放入到Undo tablespace内, 而是存在于对象原本的表空间的回收站内.
Oracle回收站将用户所做的drop语句操作记录在一个系统表内. 即将被删除的对象写到1个数据字典中, 当不在需要被删除的对象时, 可以使用purge命令队回收站空间进行清除.
但是此时被删除的表原被所占物理数据块会被标记成可以用, 也就是说可以被其他新数据所覆盖. 而在这种事情发生之前, 用户就可以利用flashback 从回收站中恢复被误删除的表.
当1个被drop掉的表被flashback 恢复时, 这张表的约束, 包括pk, ui, not null都会被恢复. 但是外键约束不会被恢复, 需要手动添回.
我们可以通过如下命令来查看系统中回收站是否被启用:
SQL> show parameter recyclebin
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
recyclebin string on
SQL>
也可以禁用/启用 回收站, 当然一旦禁用, flashback drop将无法生效
alter system/session set recyclebin=on|off;
使用如下命令清空回收站(当前用户)
SQL> purge user_recyclebin;
Recyclebin purged.
7.1 Flashback drop 的例子:继续用上面的t3表作例子:
SQL> select constraint_name, constraint_type, table_name from user_constraints where table_name = 'T3';
CONSTRAINT_NAME C TABLE_NAME
------------------------------ - ------------------------------
T3_EMPNO_PK P T3
T3_T4_DEPTNO_FK R T3
SQL> select count(1) from t3;
COUNT(1)
----------
14
可见此时T3 具有1个主键和外键约束.
1.drop掉表T3
SQL> drop table t3;
Table dropped.
2.查看回收站, 见到有一条关于T3的记录:
SQL> show recyclebin;
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
T3 BIN$+jNxn7Lfw3XgQAB/AQApBg==$0 TABLE 2014-05-25:15:04:55
记录中还包括drop的时间哦.
3. 使用flashback drop 恢复表T3
SQL> flashback table t3 to before drop;
Flashback complete.
4.这时检查T3, 发现所有数据行被恢复, 主键也被恢复(被renamed哦), 但是外键就被丢失了.
SQL> select count(1) from t3;
COUNT(1)
----------
14
SQL> select constraint_name, constraint_type, table_name from user_constraints where table_name = 'T3';
CONSTRAINT_NAME C TABLE_NAME
------------------------------ - ------------------------------
BIN$+jNxn7Ldw3XgQAB/AQApBg==$0 P T3
本文着重介绍了几个成员, 但是还有一些不常用的成员例如flashback database(例如恢复被删除的用户)就不详细介绍了.