前几天在给公司的员工讲一个案例的提到这个问题。
其实当时提到了这个特点,DROP TABLE会进入回收站,但是DROP PARTITION并不会,因此DROP PARTITION之后,数据无法简单的回复,只能通过逻辑或物理备份的方式来进行数据的回复。
SQL> create table t_drop (id number);
Table created.
SQL> drop table t_drop;
Table dropped.
SQL> select object_name, original_name from recyclebin;
OBJECT_NAME ORIGINAL_NAME
------------------------------ --------------------------------
BIN$xJhZqpmfWZXgRDzZK0pZWw==$0 T_DROP
SQL> create table t_part_drop (id number) partition by range (id)
2 (partition p1 values less than (10),
3 partition p2 values less than (20),
4 partition p3 values less than (30),
5 partition pmax values less than (maxvalue));
Table created.
SQL> insert into t_part_drop tb select rownum from user_objects;
176 rows created.
SQL> commit;
Commit complete.
SQL> alter table t_part_drop drop partition p1;
Table altered.
SQL> select object_name, original_name from recyclebin;
OBJECT_NAME ORIGINAL_NAME
------------------------------ --------------------------------
BIN$xJhZqpmfWZXgRDzZK0pZWw==$0 T_DROP
本来只是普及一下这个常识,不过有人问我Oracle为什么没有实现将删除分区放在回收站中。这个问题问的很好,因为如果这个功能很容易实现,那么Oracle肯定早就实现了,而到了11.2中Oracle仍然没有实现这个功能,那么一定说明这个功能不是无法实现,就是实现的困难太大。
回收站的实现并不复杂,当一张表被删除的时候,Oracle没有直接释放表在表空间上的空间占用,而是将表简单的打了个标识,这样在正常查询数据字典时就不会看到这张被删除的表,而如果需要恢复这张表时,只需要将标识位改回来既可。
那么同样是修改数据字典,为什么不能将被删除的分区通过标识的方法放到回收站中呢,这是因为,对于表而言,删除操作是将一个整理完全删除。而对于分区的删除,是删除整体中的一个部分。对于删除这个动作其实并没有太大的影响,但是回收站的功能不是为了删除,而是为了可以快速的恢复。对表而言,直接恢复整体不存在任何的问题,即使同名对象存在,也只需改个名字既可。而对于删除分区的恢复而言, tb 问题就不那么简单了。由于分区表并没有删除,因此这个表仍然可以继续进行操作,虽然某个分区被删除了,但是除非是范围分区中的MAXVALUE分区和列表分区中的DEFAULT分区,否则再插入原分区对应的数据时,并不会报错,而是会插入到其他分区中:
SQL> select * from t_part_drop partition (p2);
ID
----------
10
11
12
13
14
15
16
17
18
19
10 rows selected.
SQL> insert into t_part_drop values (5);
1 row created.
SQL> select * from t_part_drop partition (p2);
ID
----------
10
11
12
13
14
15
16
17
18
19
5
11 rows selected.
原表应该插入分区P1的数据,由于分区P1被删除,因此现在满足分区P2的条件,被插入到分区P2中,考虑这种情况下,如果直接恢复P1分区会怎样。
显然这不是一个简单的数据字典的修改就能解决的问题,不但涉及到分区数据改变的问题,还必然会带来全局和本地索引失效的问题,更重要的是,可能带来主键冲突的情况。
这还只是分区表进行了DML的情况,如果删除分区后,分区表又进行了DDL,比如新SPLIT了P1分区,那么删除分区的恢复操作就更无法进行了。
如果一个功能觉得很简单就可以实现,但是Oracle却一直没有实现,那么很可能实现这个功能并不像想象的那么简单。