前几天在给公司的员工讲一个案例的提到这个问题。
其实当时提到了这个特点,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 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没有直接释放表在表空间上的空间占用,而是将表简单的打了个标识,这样在正常查询数据字典时就不会看到这张被删除的表,而如果需要恢复这张表时,只需要将标识位改回来既可。
那么同样是修改数据字典,为什么不能将被删除的分区通过标识的方法放到回收站中呢,这是因为,对于表而言,删除操作是将一个整理完全删除。而对于分区的删除,是删除整体中的一个部分。对于删除这个动作其实并没有太大的影响,但是回收站的功能不是为了删除,而是为了可以快速的恢复。对表而言,直接恢复整体不存在任何的问题,即使同名对象存在,也只需改个名字既可。而对于删除分区的恢复而言,问题就不那么简单了。由于分区表并没有删除,因此这个表仍然可以继续进行操作,虽然某个分区被删除了,但是除非是范围分区中的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却一直没有实现,那么很可能实现这个功能并不像想象的那么简单。