Recovering Tables Using Oracle Flashback Table

一、Using Flashback Drop and Managing the Recycle Bin

当你删除了一张表,数据库并没有立即移除该表所占用的空间。
数据库重命名这张表并且将这张表所有关联的对象放置在了recycle bin中。在recyclebin中,万一表被误删除了,可以在后面恢复。
这种特性叫做flashback drop。并且FLASHBACK TABLE 语句常常被用来恢复表。

** 什么是Recycle bin
——————**

recycle bin 实际是一个数据字典表,包含了删除对象的信息。
被删除的表和相关的对象如index,constraints,nested table
等等并没有从物理空间移除,仍然使用空间。
这些表空间仍然占用用户表空间配额,直到指定purged 从recycle bin
中清空,或者由于表空间限制从数据库中清除。

每一个用户都有自己的recycle bin,除非一个用户
用户具有sysdba权限,那么其他用户的recycle bin 可以被这个用户所访问。
使用下列语句可以查看recycle bin中的对象。

SELECT * FROM RECYCLEBIN;

例如:

SQL> show user;
USER is "TEST"
SQL> select * from tab;

TNAME                  TABTYPE  CLUSTERID
------------------------------ ------- ----------
TEST                   TABLE

SQL> select count(*) from test;

  COUNT(*)
----------
    14

SQL> drop table test;

Table dropped.

SQL> select count(*) from test;
select count(*) from test
                     *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL> select object_name,droptime from recyclebin;

OBJECT_NAME            DROPTIME
------------------------------ -------------------
BIN$abQywaP+LU3gU/0rqMCfkw==$0 2018-04-13:12:23:22

SQL> 

在recyclebin 中,只有 DROP TABLE SQL 语句的对象。它将标的及表相关的对象添加到recyclebin中,以便于作为一个组来恢复。除了
表自身以外,添加的表的相关的对象包括以下:
Nests tables 嵌套表
LOB segments LOB 段
Indexes 索引
Constraints 约束(包括外键约束)
Triggers 触发器
Clusters 聚蔟

当删除一个表空间包括contents是,在表空间中的对象不再放置在recyclebin中,并且数据库在recyclebin中访问的所有的位于表空间中的对象。
如果删除表空间不包括contents,表空间为空。

当你删除一个用户,任何属于该用户的对象都不会放在recyclebin中,并且在recyclebin中的任何对象都会被清空。
如:
SQL> conn  / as sysdba
        Connected.
        SQL> create user test_user identified by test_user;

        User created.

        SQL> grant create tablespace to test_user;

        Grant succeeded.

        SQL> grant drop tablespace to test_user;

        Grant succeeded. 
        SQL> grant connect,resource to test_user;

        Grant succeeded.

        SQL> conn test_user/test_user;
        Connected.
        SQL> 
        SQL> create tablespace test_user datafile '/home/oracle/test_user01.dbf' size 5m;

        Tablespace created.

        SQL> create table test_user01(id number(3)) tablespace test_user storage(initial 10k);

        Table created.

        SQL> insert into test_user01 values (1);

        1 row created.

        SQL> commit;

        Commit complete.

        SQL> 
        当前用户删除表并在回收站中查看
        SQL> drop table test_user01;

        Table dropped.

        SQL> select * from tab;

        TNAME                  TABTYPE  CLUSTERID
        ------------------------------ ------- ----------
        BIN$abi0/kvAN1DgU/0rqMCAtw==$0 TABLE

        SQL> 

        使用具有删除用户权限的用户删除当前用户

        SQL> conn / as sysdba
        Connected.
        SQL> drop user test_user;

        User dropped.
        SQL> select  * from recyclebin;

        no rows selected

        因此,当删除用户对象的时候,属于用户中的所有的对象都会被删除。





    当你删除一个聚蔟,该聚蔟的成员表都不会放置在recyclebin中,并且在recyclebin 中的之前成员表中的信息也会被清空。

    示例:
        首先创建一个聚蔟表
        SQL> create cluster personel (department number(2))
        2  size 1024
        3  storage (initial 100k next 10k);

        Cluster created.

        创建一个聚蔟索引    

        SQL> create index idx_depno on cluster personel;

        Index created.

        创建两个聚蔟表

        SQL> create table dept_10 cluster personel (deptno)
        2  as
        3  select * from scott.emp where deptno = 10;

        Table created.

        SQL> create table dept_20 cluster personel (deptno)
        2  as
        3  select * from scott.emp where deptno = 20 ;

        Table created.

        SQL> 

        查看tab中的表
        SQL> select * from tab;

        TNAME                  TABTYPE  CLUSTERID
        ------------------------------ ------- ----------
        DEPT_10                TABLE        1
        DEPT_20                TABLE        2
        PERSONEL               CLUSTER
        TEST_USER01            TABLE

        SQL> 
        删除聚蔟表
        SQL> drop cluster personel;
        drop cluster personel
        *
        ERROR at line 1:
        ORA-00951: cluster not empty


        SQL> drop cluster personel including tables;

        Cluster dropped.

        SQL> 

        查看回收站信息
        SQL> select * from recyclebin;

        no rows selected
当你删除一个类型,任何独立对象例如子类型也不会放在recyclebin中,而且任何之前的独立的对象在recyclebin中也会被清空。
示例如上。


Recyclebin中的对象名

当把一个都删除的表移动到recyclebin中,表和他关联的对象将会生成一个系统名称。这样如果有多个相同的表名就可以避免引起冲突。
下面是可能发生的情况。

    一个用户删除了一张表,并且使用相同的名称重建了该表,然后再次删除。

    示例:
SQL> conn / as sysdba
            Connected.
            SQL> create user test_drop identified by test_drop ;

            User created.

            SQL> grant resource,connect to test_drop ;

            Grant succeeded.

            SQL> conn test_drop /test_drop;
            Connected.
            SQL> create table test_drop(id number(2)) tablespace test_user storage(initial 100k next 10k);

            Table created.

            SQL> insert into test_drop values(1);

            1 row created.

            SQL> commit;

            Commit complete.

            SQL> drop table test_drop;

            Table dropped.

        查看recyclebin中已删除的对象。

            SQL> select object_name,droptime from recyclebin;

            OBJECT_NAME            DROPTIME
            ------------------------------ -------------------
            BIN$abukS7Z3PQjgU/0rqMD5IA==$0 2018-04-13:21:13:44

            SQL> 

        重新创建删除的对象
            SQL> create table test_drop(id number(2)) tablespace test_user storage(initial 100k next 10k);

            Table created.
        查看创新创建的表的内容

            SQL> select * from test_drop;

            no rows selected
        再次进行删除重建的表

            SQL> drop table test_drop;

            Table dropped.
        再次查看回收站中的表

            SQL> select object_name,droptime from recyclebin;

            OBJECT_NAME            DROPTIME
            ------------------------------ -------------------
            BIN$abukS7Z3PQjgU/0rqMD5IA==$0 2018-04-13:21:13:44
            BIN$abukS7Z4PQjgU/0rqMD5IA==$0 2018-04-13:21:16:13

            SQL> 
        发现删除的表的名称相同。
        再次进行闪回会发生什么样的情况?

            SQL> flashback table test_drop to before drop;

            Flashback complete.

            SQL> select * from tab;

            TNAME                  TABTYPE  CLUSTERID
            ------------------------------ ------- ----------
            BIN$abukS7Z3PQjgU/0rqMD5IA==$0 TABLE
            TEST_DROP              TABLE

            SQL> flashback table test_drop to before drop;
            flashback table test_drop to before drop
            *
            ERROR at line 1:
            ORA-38312: original name is used by an existing object
    发现仅仅闪回了最近删除的一张表。
    两个用户有相同名称的表,并且两个用户都删除了他们各自的表。

    重命名格式如下:

    BIN$unique_id$version

    unique_id 是一个26个字符组成的对象的唯一的标识,数据库中的recyclebin中的名称具有唯一性。

    示例:

    创建两个用户并授权
SQL> conn / as sysdba
            Connected.
            SQL> create user test_drop01 identified by test_drop01 default tablespace users;

            User created.

            SQL> create user test_drop02 identified by test_drop01 default tablespace users;

            User created.

            SQL> grant resource,connect to test_drop01;

            Grant succeeded.

            SQL> grant resource,connect to test_drop02;

            Grant succeeded.

            SQL> conn test_drop01 / test_drop01;
            Connected.

            在两个用户下分别创建两张同名的表并删除此表

            在用户test_drop01下创建一张表test_drop01

            SQL> conn test_drop01 / test_drop01;
            Connected.
            SQL> create table test_drop01(id number(2)) tablespace test_user storage (initial 100k next 10k);

            Table created.

            SQL> insert into test_drop01 values(1);

            1 row created.

            SQL> commit;
            Commit complete.
            在用户test_drop02下创建一张表test_drop01
            SQL> conn test_drop02 / test_drop02;
            Connected.
            SQL> create table test_drop01(id number(2)) tablespace test_user storage (initial 100k next 10k);

            Table created.

            SQL> insert into test_drop01 values(1);

            1 row created.

            SQL> commit;

            Commit complete.

            分别删除两个用户下的表test_drop01

            SQL> conn test_drop01 / test_drop01;
            Connected.
            SQL> select * from tab;

            TNAME                  TABTYPE  CLUSTERID
            ------------------------------ ------- ----------
            TEST_DROP01            TABLE

            SQL> drop table test_drop01;

            Table dropped.

            SQL> conn test_drop02 / test_drop02;
            Connected.
            SQL> select * from tab;

            TNAME                  TABTYPE  CLUSTERID
            ------------------------------ ------- ----------
            TEST_DROP01            TABLE

            SQL> drop table test_drop01;

            Table dropped.

            查看回收站的对象

            SQL> conn test_drop01 / test_drop01;
            Connected.
            SQL> select object_name,droptime from recyclebin;

            OBJECT_NAME            DROPTIME
            ------------------------------ -------------------
            BIN$abx2X3twPqngU/0rqMBk5A==$0 2018-04-13:22:12:29
            SQL> conn test_drop02 / test_drop02;
            Connected.
            SQL> select object_name,droptime from recyclebin;

            OBJECT_NAME            DROPTIME
            ------------------------------ -------------------
            BIN$abx34G9APrLgU/0rqMDgOA==$0 2018-04-13:22:12:54

            SQL> 
        发现两个用户下的表的名称一样,但是recyclebin中的对象名称不一样。

二、开启和关闭recyclebin

只有当开启recyclebin的时候,删除的表和其独立的对象才会被放在 recyclebin中。
当recyclebin关闭的时候,删除的表和其独立的对象不会被放在recyclebin中;如果被删除了,那么
需要使用其他的方法进行恢复它们(如从backup中进行恢复)。

关闭recycle bin并不会清空或者影响已存在在 recyclebin中的对象。recyclebin默认是开启的。

开启和关闭 recyclebin需要改变 recycle bin的初始化参数。这个参数不是动态的,因此当使用
ALTER SYSTEM 语句的时候需要重新启动数据库。

使用下列语句:

会话级修改:
SQL> conn / as sysdba
        Connected.
        SQL> ALTER SESSION SET RECYCLEBIN = ON;

        Session altered.

        SQL> 
系统级修改:
SQL> ALTER SYSTEM SET recyclebin = off scope = spfile;

        System altered.

        SQL> show parameter recyclebin;

        NAME                     TYPE                 VALUE
        ------------------------------------ -------------------------------- ------------------------------
        recyclebin               string               ON
        SQL> show parameter recyclebin;

        NAME                     TYPE                 VALUE
        ------------------------------------ -------------------------------- ------------------------------
        recyclebin               string               OFF
        SQL> shu immediate;
        Database closed.
        Database dismounted.
        ORACLE instance shut down.
        SQL> startup
        ORACLE instance started.

        Total System Global Area  534462464 bytes
        Fixed Size          2254952 bytes
        Variable Size         285214616 bytes
        Database Buffers      234881024 bytes
        Redo Buffers           12111872 bytes
        Database mounted.
        Database opened.
        SQL> show parameter recyclebin;

        NAME                     TYPE                 VALUE
        ------------------------------------ -------------------------------- ------------------------------
        recyclebin               string               OFF
        SQL> 
    开启为 on;

三、查看和查询在recycle bin中的对象

Oracle数据库提供了两种视图为 获取信息关于在 recyclebin 中的对象

USER_RECYCLEBIN 是一个 RECYCLEBIN的同义词 用户级查看

DBA_RECYCELBIN 。可以查看所有

系统级查看
示例:
SQL> SELECT object_name,original_name FROM dba_recyclebin WHERE owner = 'TEST_DROP01';

        OBJECT_NAME            ORIGINAL_NAME
        ------------------------------ --------------------------------
        BIN$abx2X3twPqngU/0rqMBk5A==$0 TEST_DROP01

        SQL> 
用户及查看
SQL> select object_name,original_name from user_recyclebin;

        OBJECT_NAME            ORIGINAL_NAME
        ------------------------------ --------------------------------
        BIN$abx2X3twPqngU/0rqMBk5A==$0 TEST_DROP01

        SQL> 
也可以使用SQL Plus的 show recyclebin命令查看
SQL> conn test_drop01/test_drop01;
        Connected.
        SQL> show recyclebin;
        ORIGINAL NAME    RECYCLEBIN NAME        OBJECT TYPE  DROP TIME
        ---------------- ------------------------------ ------------ -------------------
        TEST_DROP01  BIN$abx2X3twPqngU/0rqMBk5A==$0 TABLE         2018-04-13:22:12:29
        SQL> 

四、清空Recycle Bin中的对象

如果你确定你不会从recyclebin中恢复对象,那么你可以使用使用 PURGE 语句从RECYCLEBIN中移除对象及其关联的对象以释放其空间。

如果你删除这些对象需要具有同样的权限。

当你使用 PURGE 语句清空一张表时,需要你知道 RECYCLEBIN 中的表名或者原始表的表名。

可以从DBA_RECYCLEBIN中来获取相关的对象的信息

示例:
SQL> select object_name,original_name from user_recyclebin;

        OBJECT_NAME            ORIGINAL_NAME
        ------------------------------ --------------------------------
        BIN$abx2X3twPqngU/0rqMBk5A==$0 TEST_DROP01

        SQL> show user;
        USER is "TEST_DROP01"
        SQL> purge table "BIN$abx2X3twPqngU/0rqMBk5A==$0";

        Table purged.

        SQL> show recyclebin;
        SQL> 
也可以使用表名来清空RECYCLEBIN的中对象

    purge  table  table_name;


也可以使用 PURGE RECYCLEBIN 来清空整个回收站。

五、从RECYCLEBIN中恢复表

使用FLASHBACK TABLE ... TO BEFORE DROP 语句从 RECYCLEBIN 中来恢复对象。

你可以指定RECYCLEBIN 中的名称或者原始表的名称来恢复表。 RENAME TO 语句可以让你重命名你想恢复的表名称。

这个操作需要你具有和DROP 这张表相同的权限。

示例:
SQL> conn test_drop02 / test_drop02;
        Connected.
        SQL> select * from tab;

        TNAME                  TABTYPE  CLUSTERID
        ------------------------------ ------- ----------
        BIN$abx34G9APrLgU/0rqMDgOA==$0 TABLE

        SQL> show recyclebin;
        ORIGINAL NAME    RECYCLEBIN NAME        OBJECT TYPE  DROP TIME
        ---------------- ------------------------------ ------------ -------------------
        TEST_DROP01  BIN$abx34G9APrLgU/0rqMDgOA==$0 TABLE         2018-04-13:22:12:54
        SQL> flashback table test_drop01 to before drop rename to test_drop;

        Flashback complete.

        SQL> select * from tab;

        TNAME                  TABTYPE  CLUSTERID
        ------------------------------ ------- ----------
        TEST_DROP              TABLE

        SQL> 
如果你多次删除一张表,那么系统生成的 recycle bin 名称是非常有用的。例如:

假如你在 recycle bin中有三个int2_admin_emp的版本,你想要恢复第二个版本。你可以执行两个
FLASHBACK TABLE 语句,或者你可以查询 RECYCLE BIN 然后闪回合适的系统生成名称。

示例:
SQL> conn test/test;
        Connected.
        SQL> select * from tab;

        no rows selected

        SQL> create table init2_admin_emp(id number(1));

        Table created.

        SQL> insert into init2_admin_emp values(1);

        1 row created.

        SQL> commit;

        Commit complete.

        SQL> drop table init2_admin_emp;

        Table dropped.

        SQL> create table init2_admin_emp(id number(1));

        Table created.

        SQL> insert into init2_admin_emp values(1);

        1 row created.

        SQL> commit;

        Commit complete.
        SQL> drop table init2_admin_emp;

        Table dropped.

        SQL> create table init2_admin_emp(id number(1));

        Table created.

        SQL> insert into init2_admin_emp values(1);

        1 row created.

        SQL> alter table init2_admin_emp add(name varchar2(2));

        Table altered.

        SQL> commit;

        Commit complete.

        SQL> drop table init2_admin_emp;

        Table dropped.

    查看recyclebin中已删除的三个对象:
        SQL> select object_name,original_name,droptime from recyclebin;

        OBJECT_NAME            ORIGINAL_NAME            DROPTIME
        ------------------------------ -------------------------------- -------------------
        BIN$ab0hc2pRQH7gU/0rqMCsWg==$0 INIT2_ADMIN_EMP           2018-04-13:23:00:19
        BIN$ab0hc2pSQH7gU/0rqMCsWg==$0 INIT2_ADMIN_EMP           2018-04-13:23:00:57
        BIN$ab0hc2pTQH7gU/0rqMCsWg==$0 INIT2_ADMIN_EMP           2018-04-13:23:01:34

        SQL> 
恢复第二次删除的表对象

    使用两次flashback table 语句
SQL> flashback table init2_admin_emp to before drop;

        Flashback complete.
        SQL> flashback table init2_admin_emp to before drop rename to init2_sed_admin_emp;

        Flashback complete.
    注意:当使用两次flashback table语句时,第二次使用的flashback 语句需要重新命名才能闪回成功。不然会有
    ORA-38312的错误。

恢复独立的对象:

当你从 recycle bin 中恢复表时,独立的对象如索引不会随着表的恢复而被恢复,独立的对象依然会保持系统生成的
recycle bin 的名称。你必须手动重新命名独立的对象来恢复它们的原始名称。如果打算为独立的对象恢复原始的名称,
确保你恢复表前的每一个独立对象的系统生成的 recycle bin 的名称。


示例:

下列示例是恢复JOB_HISTORY 中的一些索引的原始名称,从HR  样例中。示例假设你已经使用HR用户登录。
SQL> conn hr / hr ;
        Connected.
        SQL> select * from tab;

        TNAME                  TABTYPE  CLUSTERID
        ------------------------------ ------- ----------
        COUNTRIES              TABLE
        DEPARTMENTS            TABLE
        EMPLOYEES              TABLE
        EMP_DETAILS_VIEW           VIEW
        JOBS                   TABLE
        JOB_HISTORY            TABLE
        LOCATIONS              TABLE
        REGIONS                TABLE

        8 rows selected.

        SQL> select object_name,original_name,type from recyclebin;

        OBJECT_NAME            ORIGINAL_NAME                            TYPE
        ------------------------------ -------------------------------- -------------------------
        BIN$ab1TxluPQPjgU/0rqMAo2g==$0 JHIST_EMPLOYEE_IX             INDEX
        BIN$ab1TxluQQPjgU/0rqMAo2g==$0 JHIST_JOB_IX                      INDEX
        BIN$ab1TxluOQPjgU/0rqMAo2g==$0 JHIST_DEPARTMENT_IX               INDEX
        BIN$ab1TxluRQPjgU/0rqMAo2g==$0 JHIST_EMP_ID_ST_DATE_PK           INDEX
        BIN$ab1TxluSQPjgU/0rqMAo2g==$0 JOB_HISTORY                       TABLE

        SQL> 
恢复表
SQL> flashback table "BIN$ab1TxluSQPjgU/0rqMAo2g==$0" to before drop;

        Flashback complete.

        SQL> select object_name,original_name,type from recyclebin;

        no rows selected

        SQL> select index_name from user_indexes where table_name = 'JOB_HISTORY';

        INDEX_NAME
        ------------------------------
        BIN$ab1TxluOQPjgU/0rqMAo2g==$0
        BIN$ab1TxluPQPjgU/0rqMAo2g==$0
        BIN$ab1TxluRQPjgU/0rqMAo2g==$0
        BIN$ab1TxluQQPjgU/0rqMAo2g==$0

        SQL> 

    查看索引:
        SQL> select object_name,original_name,type from recyclebin;

        no rows selected

        SQL> select index_name from user_indexes where table_name = 'JOB_HISTORY';

        INDEX_NAME
        ------------------------------
        BIN$ab1TxluOQPjgU/0rqMAo2g==$0
        BIN$ab1TxluPQPjgU/0rqMAo2g==$0
        BIN$ab1TxluRQPjgU/0rqMAo2g==$0
        BIN$ab1TxluQQPjgU/0rqMAo2g==$0

        SQL> 
重新命名索引:
SQL> alter index "BIN$ab1TxluPQPjgU/0rqMAo2g==$0"  rename to JHIST_EMPLOYEE_IX; 

        Index altered.

        SQL> alter index "BIN$ab1TxluQQPjgU/0rqMAo2g==$0" rename to JHIST_JOB_IX;

        Index altered.

        SQL> alter index "BIN$ab1TxluOQPjgU/0rqMAo2g==$0" rename to JHIST_DEPARTMENT_IX;

        Index altered.

        SQL> alter index "BIN$ab1TxluRQPjgU/0rqMAo2g==$0" rename to JHIST_EMP_ID_ST_DATE_PK;

        Index altered.

        SQL> 

    查看索引:

        SQL> select index_name from user_indexes where table_name = 'JOB_HISTORY';

        INDEX_NAME
        ------------------------------
        JHIST_DEPARTMENT_IX
        JHIST_EMPLOYEE_IX
        JHIST_EMP_ID_ST_DATE_PK
        JHIST_JOB_IX

        SQL>    
如果索引太多,使用批处理语句进行重命名
前提是表还没有恢复之前。
SQL> select 'alter index ' || '"'|| object_name || '"' || ' rename to ' || original_name || ';'  statement from recyclebin where type = 'INDEX';

        STATEMENT
        ------------------------------------------------------------------------------------------
        alter index "BIN$ab1TxlukQPjgU/0rqMAo2g==$1" rename to BIN$ab1TxluZQPjgU/0rqMAo2g==$0;
        alter index "BIN$ab1TxlulQPjgU/0rqMAo2g==$1" rename to BIN$ab1TxluaQPjgU/0rqMAo2g==$0;
        alter index "BIN$ab1TxlumQPjgU/0rqMAo2g==$1" rename to BIN$ab1TxlubQPjgU/0rqMAo2g==$0;
        alter index "BIN$ab1TxlunQPjgU/0rqMAo2g==$1" rename to BIN$ab1TxlucQPjgU/0rqMAo2g==$0;

        SQL> 
    注意,多次操作删除后,原始名则不会为原来的。因此需要恢复需要知道原来的索引。
    注意,执行批处理语句需要先恢复表,才能执行,不然会报错误ORA-38301。

记于 2018年4月13日,23:49

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值