Oracle Flashback(闪回) 详解(3)

而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 的FlashBack

1. 首先创建两张相同内容的表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

6.2.2 基于restore point 的flashback table

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 Drop

通过上面的介绍以及例子, 相信大家都知道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(例如恢复被删除的用户)就不详细介绍了.

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/76c001c40ce0f002b631e430394c3c1a.html