--==============================================
-- Oracle 闪回特性 (FLASHBACK DROP & RECYCLEBIN)
--==============================================
FLASHBACK DROP 特性允许在不丢失任何数据库的情况下将指定的表恢复至其被删除的时间点,并保持数据库为当前状态。闪回删除并不是
真正的删除表,而是把该表重命名并放入回收站,类似于 Windows 的回收站一样。当某个活动对象需要使用该表所占用的空间时,该表才会被真
正删除。只要空间未被复用,该表即可恢复。本文主要讲述了 FLASHBACK DROP 特性以及闪回特性中回收站 (RECYCLEBIN) 的管理。
一、 FLASHBACK DROP 的功能
将先前删除的表恢复到删除之前的状态
恢复该表的索引以及触发器,授权
恢复该表的约束,包括唯一约束、主键约束、非空约束。外键约束不可恢复
可以实现基于系统和基于会话的 flash drop 操作
alter system set recyclebin = on | off ;
alter session set recyclebin = on | off ;
drop table ( oracle 10g ) 命令并不真正删除表 , 在内部被映射为 rename 命令 , 即是将其重命名之后放入回收站。
二、理解表重名的过程
scott@ORCL > create table tb_emp as select * from emp ; -- 基于 emp 表来创建表 tb_emp
scott@ORCL > alter table tb_emp add constraint empno_pk -- 添加主键约束 , 将产生主键索引
2 primary key ( empno );
scott@ORCL > alter table tb_emp add constraint ename_uk -- 添加唯一约束 , 将产生唯一索引
2 unique ( ename );
scott@ORCL > alter table tb_emp add constraint sal_ck check ( sal > 0 ); -- 添加 check 约束
scott@ORCL > alter table tb_emp modify job constraint job_nn not null; -- 添加非空约束
scott@ORCL > alter table tb_emp add constraint dept_fk -- 添加外键约束
2 foreign key ( deptno ) references dept ( deptno ) on delete cascade ;
scott@ORCL > select constraint_name , constraint_type -- 查看 tb_emp 表上的所有约束
2 from user_constraints where table_name = 'TB_EMP' ;
CONSTRAINT_NAME C
--------------- -
EMPNO_PK P
ENAME_UK U
SAL_CK C
JOB_NN C
DEPT_FK R
-- 下面查看表 tb_emp 所在文件的 id, 块的起始 id, 大小 , 以及该对象的对象 id 等
sys@ORCL > select file_id , block_id , bytes from dba_extents where segment_name = 'TB_EMP' ;
FILE_ID BLOCK_ID BYTES
---------- ---------- ----------
4 393 65536
sys@ORCL > select object_name , object_id from dba_objects -- 查看表 tb_emp 的对象 ID
2 where object_name = 'TB_EMP' ;
OBJECT_NAME OBJECT_ID
-------------------- ----------
TB_EMP 54493
-- 对表进行重命名
scott@ORCL > alter table tb_emp rename to tb_employees ;
sys@ORCL > select file_id , block_id , bytes from dba_extents -- 重命名后所在文件的 id, 块的起始 id, 大小没有发生变化
2 where segment_name = 'TB_EMPLOYEES' ;
FILE_ID BLOCK_ID BYTES
---------- ---------- ----------
4 393 65536
sys@ORCL > select object_name , object_id from dba_objects -- 重命名后对象 ID 没有发生变化
2 where object_name = 'TB_EMPLOYEES' ;
OBJECT_NAME OBJECT_ID
-------------------- ----------
TB_EMPLOYEES 54493
scott@ORCL > select index_name , index_type -- 重命名后索引和约束也没有发生变化
2 from user_indexes where table_name = 'TB_EMPLOYEES'
3 union all
4 select constraint_name , constraint_type
5 from user_constraints where table_name = 'TB_EMPLOYEES' ;
INDEX_NAME INDEX_TYPE
------------------------------ ---------------------------
EMPNO_PK NORMAL
ENAME_UK NORMAL
EMPNO_PK P
ENAME_UK U
SAL_CK C
JOB_NN C
DEPT_FK R
从上面的演示可以看出对于表的重命名仅仅是修改了表名,而对于表对象的 ID ,以及表存放的位置,块的起始,大小等并未发生实质
性的变化。
三、删除表并实施闪回
1. 删除表 tb_employees 并查看回收站的信息
scott@ORCL > drop table tb_employees ;
scott@ORCL > select object_name , original_name , can_undrop ,
2 base_object from user_recyclebin ;
OBJECT_NAME ORIGINAL_NAME CAN BASE_OBJECT
------------------------------ -------------------------------- --- -----------
BIN$k1zC3yEiwZvgQAB / AQBRVw == $0 TB_EMPLOYEES YES 54493
BIN$k1zC3yEhwZvgQAB / AQBRVw == $0 ENAME_UK NO 54493
BIN$k1zC3yEgwZvgQAB / AQBRVw == $0 EMPNO_PK NO 54493
scott@ORCL > select count ( 1 ) from "BIN$k1zC3yEiwZvgQAB/AQBRVw==$0" ; -- 可以使用回收站名来访问对象,但要对对象加双引号
COUNT ( 1 )
----------
13
2. 实施闪回并查看闪回后的情况
scott@ORCL > flashback table tb_employees to before drop ; -- 进行闪回
Flashback complete .
scott@ORCL > select count ( 1 ) from tb_employees ; -- 闪回后表存在并且可以访问
COUNT ( 1 )
----------
13
scott@ORCL > select index_name , index_type -- 查看闪回后索引,约束的情况,发现其名称仍然为 BIN$ 名称
2 from user_indexes where table_name = 'TB_EMPLOYEES'
3 union all
4 select constraint_name , constraint_type
5 from user_constraints where table_name = 'TB_EMPLOYEES' ;
INDEX_NAME INDEX_TYPE
------------------------------ ---------------------------
BIN$k1zC3yEgwZvgQAB / AQBRVw == $0 NORMAL
BIN$k1zC3yEhwZvgQAB / AQBRVw == $0 NORMAL
BIN$k1zC3yEcwZvgQAB / AQBRVw == $0 P
BIN$k1zC3yEdwZvgQAB / AQBRVw == $0 U
BIN$k1zC3yEewZvgQAB / AQBRVw == $0 C
BIN$k1zC3yEfwZvgQAB / AQBRVw == $0 C
从上面的查询可以看出闪回之后索引约束的名字还是使用了以 BIN 开头,由系统生成的名字,可以将其改回,但外键约束已经不存在了。
3. 尝试对表 DML 操作
scott@ORCL > insert into tb_employees ( empno , ename , job , sal , deptno )
2 select 9999 , 'Robinson' , 'DBA' , 3000 , 50 from dual ;
1 row created . -- 可以成功插入, deptno 列的外键约束已经被删除,故 deptno 为号成功插入
scott@ORCL > alter index "BIN$k1zC3yEgwZvgQAB/AQBRVw==$0" rename to EMPNO_PK ;
Index altered . -- 将 BIN 开头的索引改回原来的名字,其余的约束名修改在此省略
4. 下面演示表空间不足时无法闪回表删除的问题
sys@ORCL > select tablespace_name , sum ( bytes / 1024 / 1024 ) || ' M'
2 from dba_free_space where tablespace_name = 'TBS1'
3 group by tablespace_name ; -- 表空间 tbs1 的可用空间为 M
TABLESPACE_NAME SUM ( BYTES / 1024 / 1024 )|| 'M'
------------------------------ ---------------------------------
TBS1 .9375 M
flasher@ORCL > create table tb1 tablespace tbs1 as select * from dba_objects
2 where rownum < 6000 ;
sys@ORCL > select tablespace_name , sum ( bytes / 1024 / 1024 ) || ' M'
2 from dba_free_space where tablespace_name = 'TBS1'
3 group by tablespace_name ; -- 在该表空间创建表 tb1 之后,可用空间为 .25M
TABLESPACE_NAME SUM ( BYTES / 1024 / 1024 )|| 'M'
------------------------------ ---------------------------------
TBS1 .25 M
flasher@ORCL > drop table tb1 ; -- 将表 tb1 删除
flasher@ORCL > show recyclebin ; -- 删除后的对象位于回收站中
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
TB1 BIN$k2oZsEiaG7LgQAB / AQAZMA == $0 TABLE 2010 - 10 - 25 : 12 : 05 : 18
flasher@ORCL > select object_name , original_name , can_undrop ,
2 base_object from user_recyclebin ;
OBJECT_NAME ORIGINAL_N CAN BASE_OBJECT
------------------------------ ---------- --- -----------
BIN$k2oZsEiaG7LgQAB / AQAZMA == $0 TB1 YES 54531
sys@ORCL > select tablespace_name , sum ( bytes / 1024 / 1024 ) || ' M'
2 from dba_free_space where tablespace_name = 'TBS1'
3 group by tablespace_name ; -- 表空间 tbs1 显示的可用空间已返还为 1M
-- 但并不是真正为 M, 在需要表空间时 , 将自动清除回收站最老的对象 , 以满足当前空间需求
TABLESPACE_NAME SUM ( BYTES / 1024 / 1024 )|| 'M'
------------------------------ -------------------------------
TBS1 .9375 M
sys@ORCL > select tablespace_name , autoextensible -- 这个查询可以看出表空间 tbs1 不能自动扩展
2 from dba_data_files where tablespace_name = 'TBS1' ;
TABLESPACE_NAME AUT
--------------- ---
TBS1 NO
flasher@ORCL > create table tb2 tablespace tbs1 as select * from dba_objects -- 再次在表空间创建新表 tb2
2 where rownum < 6000 ;
flasher@ORCL > show recyclebin ; -- 此时回收站中原来的表 tb1 记录被自动清除
flasher@ORCL > select object_name , original_name , can_undrop ,
2 base_object from user_recyclebin ;
no rows selected
flasher@ORCL > flashback table tb1 to before drop ; -- 此时表 tb1 不能被闪回
flashback table tb1 to before drop
*
ERROR at line 1 :
ORA - 38305 : object not in RECYCLE BIN
四、回收站的管理
每个用户都拥有自己的回收站,且可以查看在自己模式中删除的表
使用 purge 命令可以永久删除对象,回收空间
purge 命令的几种常用形式
drop table tbname purge -- 直接删除表,而不置于回收站
purge table tbname -- 清除回收站中的 tbname 表
purge index idx_name -- 清除回收站中的索引 idx_name
purge tablespace tablespace_name -- 清除该表空间中所有已删除的对象
purge tablespace tablespace_name user user_name -- 清除表空间中指定用户删除的对象
purge user_recyclebin -- 清除指定用户已删除的所有对象
purge dba_recyclebin -- 清除所有已删除的对象
五、总结
通过对上述表的删除及空间分配情况,总结如下:
1. 表的删除被映射为将表的重命名,然后将其置于回收站
2. 表的索引 , 触发器 , 授权闪回后将不受到影响 . 索引 , 触发器名字可以根据需要进行更改回原来名称
3. 对于约束,如果是外键约束,表删除之后将不可恢复,其余的约束不受影响
4. 如果要查询回收站中的对象,建议将对象名使用双引号括起来
5. 闪回的实质并不能撤销已提交的事务,而是构造倒退原有事务影响的另一个事务
6. 对于已经删除的表如果在所在的表空间新增对象由于空间不足的压力而被重用将导致闪回失败
7. 对于表空间不足时,系统会自动清除回收站中最老的对象,以满足当前需求,即采用 FIFO 原则
8. 闪回表的常用方法
flashback table tbname to before drop ;
flashback table tbname to before drop rename to newtbname;
第二条语句用于被删除的表名已经被再次重用 , 故闪回之前必须将其改名为新表名 ,schema 不变化
9. 如回收站中存在两个相同的原表名,则闪回时总是闪回最近的版本,如果闪回特定的表,需要指定
该表在回收站中的名称。如
flashback table "BIN$k1zC3yEiwZvgQAB/AQBRVw==$0" to before drop;
10.flashback drop 不能闪回 truncate 命令截断的表,而是只能恢复 drop 之后的表
11.flashback drop 不能闪回 drop user scott cascade 删除方案的操作 , 此只能用 flashback database
12. 在 system 表空间中存储的表无法启用 flashback drop ,且这些表会被立即删除
与回收站相关两个重要的视图
dba_recyclebin
user_recyclebin
六、 更多参考
有关基于用户管理的备份和备份恢复的概念请参考:
Oracle 基于用户管理恢复的处理 ( 详细描述了介质恢复及其处理 )
有关 RMAN 的恢复与管理请参考:
有关 Oracle 体系结构请参考:
Oracle 实例和Oracle 数据库(Oracle 体系结构)
Oracle 联机重做日志文件(ONLINE LOG FILE)