Oracle闪回drop和闪回查询

        Oracle提供了7种闪回技术,分别为:闪回drop、闪回查询、闪回数据归档、闪回表、闪回版本查询、闪回事务、闪回数据库。此次验证下Oracle数据库闪回drop和闪回查询。

一、闪回DROP

        又名闪回删除。

1、理解回收站(recyclebin)

        从管理的角度为每个用户“分配”一个回收站,但这个回收站并不实际开辟空间(只是个逻辑容器),当drop table时(非purge),原来的表所使用的段中的数据并没有真正的删除。实际上是把table的段名以回收站方式重命名。该段所在表空间不足需要扩展时,回收站中的信息会被自动清除。(先清除后扩展)
Oracle闪回drop和闪回查询

示例:
SQL> show parameter recyclebin   
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
recyclebin                           string      ON    

当初始化参数recyclebin为on时,每个用户都有了自己的回收站(延迟参数,session下次连接有效)
如果参数设为off 就取消了用户的回收站,那么当你drop table就相当于purge了。

SQL> create tablespace test datafile '/u01/oradata/prod/test01.dbf' size 1m;
SQL> create table scott.t1(id int) tablespace test;
SQL> select segment_name from dba_segments where tablespace_name='TEST';   查看test表空间下有了一个段
SEGMENT_NAME
T1
SQL> select sum(bytes) from dba_free_space where tablespace_name='TEST';   看这个段有多少空闲空间

SUM(BYTES)
----------
    917504

SQL> insert into scott.t1 values(1);
SQL> insert into scott.t1 select * from scott.t1;   将表空间撑满
/
/
第 1 行出现错误:
ORA-01653: 表 SCOTT.T1 无法通过string (在表空间 TEST 中) 扩展
SQL> select count(*) from scott.t1;
  COUNT(*)
----------
     65536
SQL> select sum(bytes) from dba_free_space where tablespace_name='TEST';   没有空闲空间
SQL> drop table scott.t1;
SQL> select segment_name from dba_segments where tablespace_name='TEST';
SEGMENT_NAME
---------------------------------------------------------------------------------
BIN$4KZBTYTKocDgQAB/AQAKRA==$0

SQL> select sum(bytes) from dba_free_space where tablespace_name='TEST';
SUM(BYTES)
----------
    983040

        请看,TEST表空间中的空闲空间又回来了,这说明如果test表空间不够时,这部分空闲空间是可以被重新利用的,实际上即使你设置了表空间autoextend特性,Oracle 会先使用recyclebin,若空间还不够,再考虑autoextend.

SQL> create table scott.emp1 tablespace test as select * from scott.emp;   挤占test表空间
SQL> select sum(bytes) from dba_free_space where tablespace_name='TEST';
SUM(BYTES)
----------
    917504
SQL> select segment_name from dba_segments where tablespace_name='TEST';  
SEGMENT_NAME
---------------------------------------------------------------------------------
EMP1

t1表的数据已经被冲掉了,使用闪回删除无法找回了。

2、关于回收站中的对象的闪回和清除

闪回和清除的顺序不同
闪回使用LIFO (后进先出)
清除使用FIFO (先进先出)
假设回收站里有两个t1表,看以下两条语句:

SQL> flashback table t1 to before drop;   闪回的是最新的那个t1表。
SQL> purge table t1;   清除的是最旧的那个t1表。

如果想避免混淆,可以直接给出回收站里的表名

SQL> flashback table " BIN$qrJLbL74ZgvgQKjA8Agb/A==$0" to befroe drop;  (注意双引号)
SQL> purge table "BIN$qrJLbL74ZgvgQKjA8Agb/A==$0";

SQL> purge recyclebin;   清空回收站

3、如何恢复同一个schema下准备闪回的表已有同名的对象存在,闪回drop需要重命名.

SQL> flashback table t1 to before drop rename to test_old;

4、system 表空间的对象没有回收站,所以在sys下缺省使用system表空间时,drop table会直接删除对象

5、如果一个表上面有索引和约束,drop后再闪回表,索引和约束还在吗?

create table t (id int,name char(10));
alter table t add constraint pk_t primary key(id);
insert into t values (1,'test1');
insert into t values (2,'test2');
commit;
SQL> select * from t;
        ID NAME
---------- ----------
         1 test1
         2 test2
看一眼约束和索引
SQL> select * from user_indexes;
SQL> select * from user_constraints;

SQL> drop table t;   表被drop到回收站,再看一眼约束和索引

SQL> select * from user_indexes;   索引不见了
SQL> select * from user_constraints;   约束有,但乱码(除外键约束外)

SQL> flashback table t to before drop;

再看约束和索引
SQL> select * from user_indexes;   索引回来了,但乱码
SQL> select * from user_constraints;   约束也在,但乱码

分别重命名索引和约束
SQL> alter index "BIN$yF3hbvIbioTgQAB/AQAJlg==$0" rename to pk_t;
SQL> alter table t rename constraint "BIN$yF3hbvIaioTgQAB/AQAJlg==$0" to pk_t;

6、查看闪回区内容

select OBJECT_NAME,ORIGINAL_NAME,OPERATION,CREATETIME,DROPTIME from user_recyclebin;
select * from tab;

二、闪回查询

flashback query:(用于DML 误操作并且commit)

1、要点:

利用在undo tablespace 里已经提交的undo block(未被覆盖),可以查询表的过去某个时间点的数据。
通过设置undo_retention参数设置前镜像的保留时间。
查询的语法:
select … as of scn | timestamp

2、undo_retention

可以通过show parameter undo_retention查看该参数的值,默认900,单位是秒。关于undo_retention的介绍可以查看lian链接:link

3、示例:

sys:
create table scott.student (sno int,sname char(10),sage int);
insert into scott.student values(1,'tt1',21);
insert into scott.student values(2,'tt2',22);
insert into scott.student values(3,'tt3',23);
insert into scott.student values(4,'tt4',24);
commit;

SQL> select * from scott.student;

SQL> select current_scn from v$database;   取scn 1或者查询当前时间
SQL> delete scott.student where sno=1;
SQL> commit;
SQL> select * from scott.student;

SQL> select current_scn from v$database;   取scn 2
SQL> update scott.student set sage=50;
SQL> commit;
SQL> select * from scott.student;

SQL>select * from scott.student as of scn scn1;   闪回查询到scn1;
SQL>select * from scott.student as of scn scn2;   闪回查询到scn2;

SQL>select * from scott.student as of timestamp to_timestamp('2019-03-18 11:31:01','YYYY-MM-DD HH24:MI:SS');  //闪回查询基于时间

4、查看 DELETE 及 UPDATE 操作修改的数据:

SQL> SELECT *
FROM tab AS OF TIMESTAMP  to_timestamp('time_point', 'yyyy-mm-dd hh24:mi:ss')
MINUS
SELECT *
FROM tab;
其中将查询得 tab 表在 time_point 时点之后因 DELETE 及 UPDATE 操作修改的数据。

5、查看 INSERT 操作修改的数据:

SQL> SELECT *
FROM tab
MINUS
SELECT *
FROM tab AS OF TIMESTAMP  to_timestamp('time_point', 'yyyy-mm-dd hh24:mi:ss');
其中将查询得 tab 表在 time_point 时点之后因 INSERT 操作修改的数据。

参考文章
1、http://www.cnblogs.com/autopenguin/p/5952671.html

上一篇:Oracle中表连接方式(Nested Loop、Hash join)对于表访问次数的测试


下一篇:安全专家教你如何利用Uber系统漏洞无限制的免费乘坐?