闪回删除是通过将DROP命令映射到RENAME命令实现的,因而不是真正将表删除,而是将表重命名为一个系统生成的名称,以后当活动对象需要存储空间时才可能真正删除它。如果存储空间没有被重用,那么可以将对象重命名回原来的名字而还原。如果没有提供此功能,在删除一个表后还原它的唯一方法就是执行不完整恢复,恢复到删除之前的时间点。这样做通常很耗时,并意味着会丢失其后完成的工作。
闪回删除将一个表(连同它的索引和权限)恢复到删除前的状态,而不会丢失任何用户需要的数据。此操作不需要配置,也不需要任何备份,它始终是可以使用的,除非特意禁用。操作中数据库保持当前状态,不会给用户带来任何停机时间。
闪回删除是DROP命令特有的,不能用于被TRUNCATE命令截断的表。
闪回删除(Flashback Drop)允许您将之前删除的表(但不是截断Truncate)恢复到刚好删除它之前的状态。同时还会自动恢复所有相关的索引、触发器、权限和不包括外键约束的其它约束。
1、闪回删除的实现
直到Oracle 9i版本为止,当删除一个表时,到该表的所有引用都会从数据字典中删除。尽管表的数据块仍存在,但是无法找到它们,因为数据字典没有记录哪些块属于删除的表。因而恢复删除的表的唯一方法就是执行时间点恢复。
从Oracle 10g版本开始,Drop table命令的实现方式完全不一样。数据库中根本没有删除表,而只是重命名。Oracle在内部将Drop table命令映射到Rename命令,它将作用于表及其所有相关的索引、触发器和约束,但不包括外键约束,外键约束将被删除。可以想象,如果未删除的父表上的DML受已删除的表的内容约束,这将很荒诞。对于表的权限,由于Rename操作并没有改变对象号,因此授权仍是有效的。
既然Drop实际上是Rename,删除就有可能通过重命名回原来的名字而撤销。但是,并不能保证这样做总能成功。因为删除的表占用的空间有可能被重用。并且还会出现更复杂的情况,如在此期间创建了另一个表,并且重用了与删除的表相同的名称。
通过查看回收站可以查询删除的对象及其更改后的新名称。每个用户都有一个回收站,可以在数据字典视图user_recyclebin中查询。也可以查询全局视图dba_recyclebin。当表空间容量不足时,系统会自动重用回收站对象占用的空间,此后对象将不能恢复。
闪回删除不适用于存储在system表空间中的表,它们是被直接删除的。
2、使用闪回删除
Drop命令将表重命名为系统生成的名称
drop table <table_name> [purge];
Purge关键字指示Oracle恢复Drop的原始含义,删除该表及其所有引用,并且无法恢复。
闪回表并可重命名
flashback table <table_name> to before drop [rename to <new_name>];
重命名是必要的,防止已有同名对象被创建而无法闪回。
和表一同闪回的索引、触发器和约束都保持了它们在回收站中的名称。如果希望恢复它们原先的名称,可以在闪回操作后手动重命名。
强调两点:第一,闪回删除只适用于执行Drop命令后的恢复,而不能恢复用Truncate命令截断的表;第二,如果删除了一个用户,如使用drop user scott cascade命令级联删除了用户及其所有表,那么使用闪回将无法恢复任何该用户的对象,因为根本没有可供对象连接的用户。
使用SQL*Plus命令show recyclebin可以查看有关删除对象的信息
show recyclebin;
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
T1 BIN$nQhcJiWqRIG1ykFeF+LD3g==$0 TABLE 2016-03-13:22:59:23
如果删除了表,然后创建了具有相同名称的另一个表,并且随后也删除了它,那么在回收站中将有两个原名相同的表,但具有不同的回收站名称。默认情况下,闪回删除命令总是恢复最新版本的表。但如果需要,也可以指定希望恢复的版本的回收站名称,而不是指定原先的名称
flashback table "BIN$nQhcJiWqRIG1ykFeF+LD3g==$0" to before drop;
以下例子实验闪回删除的使用。
1)作为用户system使用SQL*Plus连接数据库
sqlplus system/mesHz2@mes
2)创建用户、表、索引和约束,插入数据
create user dropper identified by dropper account unlock;
grant connect, resource to dropper;
conn dropper/dropper
create table names(name varchar2(10));
create index idx_name on names(name);
alter table names add constraint name_u unique(name);
insert into names values('Liuluning');
commit;
3)确认模式的内容
col object_name for a30
select object_name, object_type from user_objects;
OBJECT_NAME OBJECT_TYPE
------------------------------ -------------------
NAMES TABLE
IDX_NAME INDEX
select constraint_name, constraint_type, table_name from user_constraints;
CONSTRAINT_NAME C TABLE_NAME
------------------------------ - ------------------------------
NAME_U U NAMES
4)删除该表
drop table names;
5)重新运行步骤3的查询,确认已从user_objects中删除了对象,但是仍存在系统生成的名称的约束
select object_name, object_type from user_objects;
未选定行
select constraint_name, constraint_type, table_name from user_constraints;
CONSTRAINT_NAME C TABLE_NAME
------------------------------ - ------------------------------
BIN$7vEz1hktQe2IdYDzs0QoKA==$0 U BIN$gOlcZp57RpCDWmuorgRRgA==$0
6)查询回收站以查看原始名称到回收站名称的映射
col original_name for a20
col type for a10
col ts_name for a20
select object_name, original_name, operation, type, ts_name, createtime, droptime from user_recyclebin;
OBJECT_NAME ORIGINAL_NAME OPERATION TYPE TS_NAME CREATETIME DROPTIME
------------------------------ -------------------- --------- ---------- -------------------- ------------------- -------------------
BIN$gOlcZp57RpCDWmuorgRRgA==$0 NAMES DROP TABLE USERS 2018-04-15:22:38:15 2018-04-15:22:43:20
BIN$o++vBTFJR1yYnhE9VmJNaQ==$0 IDX_NAME DROP INDEX USERS 2018-04-15:22:39:02 2018-04-15:22:43:20
可以看到,该视图中没有约束,约束只是被换了名称。
可以查询回收站中的表,但不能进行DML操作,查询时表名称应加上双引号,以便SQL*Plus能够正确的解析非标准的字符
select * from "BIN$gOlcZp57RpCDWmuorgRRgA==$0";
NAME
----------
Liuluning
7)闪回表
flashback table names to before drop;
8)重新运行步骤3和6中的查询。可以看到,表已恢复,索引和约束仍保留了删除后的名称
select object_name, object_type from user_objects;
OBJECT_NAME OBJECT_TYPE
------------------------------ -------------------
BIN$o++vBTFJR1yYnhE9VmJNaQ==$0 INDEX
NAMES TABLE
select constraint_name, constraint_type, table_name from user_constraints;
CONSTRAINT_NAME C TABLE_NAME
------------------------------ - ------------------------------
BIN$7vEz1hktQe2IdYDzs0QoKA==$0 U NAMES
select object_name, original_name, operation, type, ts_name, createtime, droptime from user_recyclebin;
未选定行
9)将索引和约束重命名回原先的名称
alter index "BIN$o++vBTFJR1yYnhE9VmJNaQ==$0" rename to idx_name;
alter table names rename constraint "BIN$7vEz1hktQe2IdYDzs0QoKA==$0" to name_u;
10)通过重新运行步骤3中的查询确认对象名称已改回
select object_name, object_type from user_objects;
OBJECT_NAME OBJECT_TYPE
------------------------------ -------------------
IDX_NAME INDEX
NAMES TABLE
select constraint_name, constraint_type, table_name from user_constraints;
CONSTRAINT_NAME C TABLE_NAME
------------------------------ - ------------------------------
NAME_U U NAMES
11)实验完毕,以用户system连接数据库,删除dropper模式
conn system/mesHz2
drop user dropper cascade;
3、管理回收站
可以使用实例参数recyclebin禁用回收站,默认值是on,意味着所有模式都有一个回收站。该参数是动态的,可以为某个会话或整个系统将其设置为off
show parameter recyclebin;
NAME TYPE VALUE
------------------------------------ ---------- ------------------------------
recyclebin string on
每个用户可以使用SQL*Plus命令show recyclebin查看回收站信息。若要了解更详细的信息,可以查询视图user_recyclebin和dba_recyclebin,前面已经有过说明。
当表空间容量不足而回收站中有许多删除对象时,Oracle将会首先重写在回收站中留存时间最长的对象。这种先进先出(FIFO)算法假定最近删除的对象最有可能被闪回。
可以使用多种形式的purge命令永久性的删除对象。
删除表并且不进入回收站
drop table <table_name> purge;
从回收站中清除表,如果存在多个相同原始名称的对象,那么将清除存在时间最久的对象,也可以通过指定回收站中的名称来避免混淆
purge table <table_name>;
purge table "BIN$gOlcZp57RpCDWmuorgRRgA==$0";
从回收站中清除索引,可以指定原始名称或回收站中名称
purge index <index_name>;
purge index "BIN$o++vBTFJR1yYnhE9VmJNaQ==$0";
从回收站中清除归属某个表空间的所有对象
purge tablespace <tablespace_name>;
从回收站中清除属于某个表空间的某个用户的所有对象
purge tablespace <tablespace_name> user <user_name>;
清除该用户删除的所有对象
purge user_recyclebin;
清除所有删除的对象
purge dba_recyclebin;
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28974745/viewspace-2139607/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/28974745/viewspace-2139607/