Oracle提供了7种闪回技术,分别为:闪回drop、闪回查询、闪回数据归档、闪回表、闪回版本查询、闪回事务、闪回数据库。此次验证下Oracle数据库闪回drop和闪回查询。
又名闪回删除。
从管理的角度为每个用户“分配”一个回收站,但这个回收站并不实际开辟空间(只是个逻辑容器),当drop table时(非purge),原来的表所使用的段中的数据并没有真正的删除。实际上是把table的段名以回收站方式重命名。该段所在表空间不足需要扩展时,回收站中的信息会被自动清除。(先清除后扩展)
示例: 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表的数据已经被冲掉了,使用闪回删除无法找回了。
闪回和清除的顺序不同
闪回使用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; 清空回收站
SQL> flashback table t1 to before drop rename to test_old;
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;
select OBJECT_NAME,ORIGINAL_NAME,OPERATION,CREATETIME,DROPTIME from user_recyclebin; select * from tab;
flashback query:(用于DML 误操作并且commit)
利用在undo tablespace 里已经提交的undo block(未被覆盖),可以查询表的过去某个时间点的数据。
通过设置undo_retention参数设置前镜像的保留时间。
查询的语法:
select … as of scn | timestamp
可以通过show parameter undo_retention查看该参数的值,默认900,单位是秒。关于undo_retention的介绍可以查看lian链接:link
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'); //闪回查询基于时间
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 操作修改的数据。
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 操作修改的数据。