闪回机制探讨
下面我们一起来详细研究下,drop闪回的原理。首先,我们构建一个适当的实验环境。
SQL> conn scott/tiger@orcl;
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as scott
SQL> col object_name format a25;
SQL> select object_name,object_id,object_type from user_objects;
OBJECT_NAME OBJECT_ID OBJECT_TYPE
------------------------- ---------- -------------------
PK_DEPT 51150 INDEX
……(篇幅原因,有删节)
PCK_MYTEST_WORK 52607 PACKAGE BODY
T 53218 TABLE
SYS_C005520 53186 INDEX
IND_T_TEST_NAME 53187 INDEX
T_TEST 53185 TABLE
14 rows selected
实验环境下,我们存在对象表T,对象编号为53218。对应的段信息为:
SQL> select segment_name, segment_type, tablespace_name, bytes from user_segments where segment_name='T';
SEGMENT_NA SEGMENT_TYPE TABLESPACE_NAME BYTES
---------- ------------------ -------------------- ----------
T TABLE USERS 65536
下面,我们尝试删除数据表T。
SQL> drop table t;
Table dropped
SQL> select * from t;
select * from t
ORA-00942: 表或视图不存在
我们重新查找对象字段视图。
SQL> select object_name,object_id,object_type from user_objects;
OBJECT_NAME OBJECT_ID OBJECT_TYPE
------------------------- ---------- -------------------
PK_DEPT 51150 INDEX
DEPT 51149 TABLE
EMP 51151 TABLE
PK_EMP 51152 INDEX
BONUS 51153 TABLE
SALGRADE 51154 TABLE
P_ACCA_LOG_USER_COUNT 52786 PROCEDURE
PCK_MYTEST_WORK 52606 PACKAGE
MY_SEQ 52578 SEQUENCE
PCK_MYTEST_WORK 52607 PACKAGE BODY
SYS_C005520 53186 INDEX
IND_T_TEST_NAME 53187 INDEX
T_TEST 53185 TABLE
BIN$/hWq4qC8ScioKlJiEL1jA 53218 TABLE
w==$0
14 rows selected
该结果没有删节。首先,发现对象T的信息已经不存在了。其次,一个以BIN$开头的数据表对象出现在视图中,而且使用了object_id为53218,与之前T所占用的object_id相同。接着让我们查看段信息。
SQL> col segment_name format a30;
SQL> select segment_name, segment_type, tablespace_name, bytes from user_segments;
SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME BYTES
------------------------------ --------------------------------
IND_T_TEST_NAME INDEX USERS 65536
SYS_C005520 INDEX USERS 65536
T_TEST TABLE USERS 65536
BIN$/hWq4qC8ScioKlJiEL1jAw==$0 TABLE USERS 65536
SALGRADE TABLE USERS 65536
BONUS TABLE USERS 65536
EMP TABLE USERS 65536
PK_DEPT INDEX USERS 65536
DEPT TABLE USERS 65536
PK_EMP INDEX USERS 65536
10 rows selected
数据段segment代表了存储。在数据段中,我们已经找不到数据表T的信息了。而新添加的BIN$却还是占据了一个位置。
最后,我们检查数据表视图。
SQL> select table_name, tablespace_name from user_tables;
TABLE_NAME TABLESPACE_NAME
------------------------------ ------------------------------
DEPT USERS
EMP USERS
BONUS USERS
SALGRADE USERS
T_TEST USERS
数据表T信息被删除了,同时那个BIN$对象并没有被识别为数据表。
那么,回收站视图的情况呢?
SQL> select object_name, original_name, operation, type ,ts_name from user_recyclebin;
OBJECT_NAME ORIGINAL_NAME OPERATION TYPETS_NAME
------------------------- --------------------------------
BIN$/hWq4qC8ScioKlJiEL1jA T DROP TABLE USERS
w==$0
user_recyclebin帮助我们揭示了BIN$对象的本来面目。这个对象是记录原数据库表T的信息。
到此处,我们的结论也就不难获得了。所谓的闪回drop,就是一种对象假删除技术。当系统参数recyclebin被设置为on的时候,Oracle是开启闪回drop功能的。
当对数据表使用drop的时候,Oracle并不是将对象直接删除,而是采用了对象改名。将删除的数据表进行改名(逻辑上),改为BIN$开头的一个编码。
这个编码占据了原有数据表的所有资源(包括对象信息和存储信息),但是不能算成为原对象的等价体。也就是说,如果我们直接操作这个修改名,系统会报错,因为Oracle不认为这个对象是一个数据表。数据表T的数据字典信息被删除,而改名的对象信息没有加入其中。
SQL> select * from BIN$/hWq4qC8ScioKlJiEL1jAw==$0;
select * from BIN$/hWq4qC8ScioKlJiEL1jAw==$0
ORA-00933: SQL 命令未正确结束
当我们进行flashback table XXX to before drop的时候,Oracle只是将原来的数据表T信息重新改回,原有空间和数据并没有改变。
那么,这部分被假删除的数据是不是要占用原有对象表空间呢?答案是肯定的。就如同Windows回收站在没有清空的情况下,是同样消耗资源一样。Oracle的回收站也有同样的特性。
当我们删除了一个对象,这个对象信息隐藏咋数据表空间中,对象是占用空间的。但是,这部分空间的消耗并不计入到表空间容量之中。当表空间分配不足的时候,这部分闪回所用的硬盘空间是可以自动的被回收。作为一般开发人员和管理人员,这部分的操作是Oracle自动完成,相当于透明的操作。
那么,有没有可能因为闪回drop表空间对象引起一些故障问题呢?我们说是可能的。笔者曾经读到过一篇博文,文章中阐述了这样的场景(这里对文章作者表示敬意):
数据库操作程序中,向一个数据表中插入大量的数据,之后报错:说用户没有drop对象权限。为什么进行的insert操作,而提示说没有drop权限呢?程序用户也的确是没有drop权限。
最后发现是表空间中,非recyclebin可用空间使用耗尽,需要回收recyclebin中的空间。在这个过程中,Oracle不是使用直接覆盖的方法,而是自动生成了drop语句命令(一种递归调用),删除那些BIN$对象。在这个过程中,使用到了用户的drop权限。
解决的方法也很简单:管理员直接purge空间既可以。
闪回与安全
看了闪回功能,对我们的drop命令也有了一层新的认识。那么,可能有些应用是需要绝对安全删除(如PCI中的一项要求!),不希望一些被drop掉的信息还保留在数据库中,存在不安全因素。
对这种情况,可以使用两种方法。一个是直接关闭recyclebin参数,设置为off。这样就关闭了闪回drop的特性了。也就不会出现安全问题。这种方法笔者认为很实用,因为在生产环境下,drop数据表的情况还是比较少的,特别是应用层面。
第二个方法就是加参数的drop语句。使用drop table XXX purge,就不会将数据表保存在回收站中了。
SQL> select count(*) from t;
COUNT(*)
----------
0
SQL> drop table t purge;
Table dropped
SQL> select count(*) from user_recyclebin;
COUNT(*)
----------
0
//对象没有经过回收站,直接被删除;
同时,下面两个命令比较有用。
ü drop tablespace XXX including contents;删除表空间的时候,不使用回收站,并连带清除回收站;
ü drop user XXX cascade;删除用户和对应用户对象的时候,不使用回收站并连带清除回收站;
闪回特性
在这个系列中,我们介绍了闪回技术中的最常用的两个分支:闪回查询和闪回drop。经过我们的分析和讨论,可以发现:闪回是一个目标,并不代表一种技术。闪回所提倡的是在我们在进行破坏性操作,并且已经在事务生效之后,希望回到原点的一种快速恢复。在闪回之前,我们可能只能依靠复杂的备份恢复过程来实现这个目标,而有了闪回,这个目标可以轻而易举的实现。
但是,有一点要注意:闪回几个分支,包括数据库闪回、闪回查询和闪回drop都是依靠不同的机制和原理。共同点是实现的目标相同。闪回查询是利用的undo机制,闪回drop是借用了重命名和空间自动回收。所以我们在理解这三个分支的时候,要建立相对独立的知识体系,不要彼此混淆。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-686496/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17203031/viewspace-686496/