Oracle中truncate删除的数据还能找到?

2023年 11月 16日 32.4k 0

Oracle的truncate删除数据操作,不会写日志,不产生回滚段,因此执行速度快,相当于Windows的shift+del,不经回收站直接删除。

如果想找回truncate删除的数据,常规的可以采用这几种方案,

(1)使用数据泵导入。操作简单,但是前提必须要有备份可用,并且会有数据的丢失。(2)使用RMAN进行不完全恢复。前提是开启备份,可将数据库恢复到truncate之前的时刻,但是恢复时间较长。

还可以采用非常规的方案,例如通过odu、prm-dul、GDUL等收费软件进行恢复,还可以使用fy_recover_data包。

FY_Recover_Data是国内曾经的Oracle ACE大佬黄玮(个人网站:http://www.hellodba.com)开发的一个package,该脚本专门用于对truncate的表进行恢复。

作者讲述这个包的原理:如果我们已经有一套元数据及数据块,然后将被TRUNCATE的用户数据块的内容取代其用户数据块的内容,是否可以"骗"过Oracle,让它读出这些数据呢?

回顾一下表扫描的过程,这个方法应该是可行的。我们只要想办法构造出一个结构相同、且具有完整元数据信息和格式化了的用户数据块的傀儡表对象,然后将被truncate的用户数据块找出,再将其数据内容部分嫁接到傀儡对象的用户数据块,让Oracle认为这是傀儡对象的数据,就能让Oracle扫描并读出数据内容。

其原理用图示描述如下,

                                                   +-------------------------+  
    | Copy Of Dummy Data File |
    | (With Formmated Blocks)|
    +-------------------------+
    ||
    /
    (Blcok Header, Block Tail)
    ||
    /
    +-------------------+ +----------------+ Table Scan +---------------+
    | Source Data File | => (Data Block Content) => | Dummy Table | ============> | Restore Table |
    |(Without Meta Data)| |(With Meta Data)| +---------------+
    +-------------------+ +----------------+

    FY_Recover_Data对于表恢复的支持性如下,

    通过使用FY_Recover_Data对truncate几种情况进行恢复测试,以验证fy_recover_data的恢复能力。

    (1)使用fy_recover_data包执行truncate恢复,truncate后未有新数据进入表。

    STEP1:创建测试表,并执行truncate

      SQL> create table test01 as select * from dba_objects;


      SQL> select count(*) from test01;
        COUNT(*)
      ----------
      86968


      SQL> truncate table test01;
      Table truncated


      SQL> select count(*) from test01;
        COUNT(*)
      ----------
      0

      STEP2:导入FY_Recover_Data.pck包

        [oracle@source-node ~]$ sqlplus as sysdba
        SQL*Plus: Release 11.2.0.4.0 Production on Tue Apr 21 10:50:17 2020
        Copyright (c) 1982, 2013, Oracle.  All rights reserved.
        Connected to:
        Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
        With the Partitioning, OLAP, Data Mining and Real Application Testing options


        SQL> @/home/oracle/FY_Recover_Data.pck -- 第一次执行发现第30行存在“&”符号,删除该符号


        Enter value for files:
        old 30: -- 1. Temp Restore and Recover tablespace & files ---
        new 30: -- 1. Temp Restore and Recover tablespace ---


        Package created.


        Warning: Package Body created with compilation errors.


        SQL> @/home/oracle/FY_Recover_Data.pck -- 删除“&”符号后导入成功


        Package created.


        Package body created.

        STEP3:开始执行恢复,只需要两个参数:schema和table_name,

          [oracle@source-node ~]$ sqlplus as sysdba
          SQL*Plus: Release 11.2.0.4.0 Production on Tue Apr 21 11:11:20 2020
          Copyright (c) 1982, 2013, Oracle.  All rights reserved.
          Connected to:
          Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
          With the Partitioning, OLAP, Data Mining and Real Application Testing options


          SQL> set time on
          11:11:43 SQL> set serveroutput on
          11:11:54 SQL> exec fy_recover_data.recover_truncated_table('TEST','TEST01');
          11:12:01: Use existing Directory Name: FY_DATA_DIR
          11:12:02: Recover Table: TEST.TEST01$
          11:12:02: Restore Table: TEST.TEST01$$
          11:12:09: Copy file of Recover Tablespace: FY_REC_DATA_COPY.DAT1
          11:12:09: begin to recover table TEST.TEST01
          11:12:09: Use existing Directory Name: TMP_HF_DIR
          11:12:09: Recovering data in datafile
          /u01/app/oracle/oradata/testdb1/users01.dbf
          11:12:09: Use existing Directory Name: TMP_HF_DIR
          11:12:39: 1242 truncated data blocks found.
          11:12:39: 86968 records recovered in backup table TEST.TEST01$$
          11:12:39: Total: 1242 truncated data blocks found.
          11:12:39: Total: 86968 records recovered in backup table TEST.TEST01$$
          11:12:39: Recovery completed.
          11:12:39: Data has been recovered to TEST.TEST01$$


          PL/SQL procedure successfully completed.

          STEP4:根据恢复日志,会创建临时中转表test01$和test01$$,恢复的数据保存在test01$$中,

            SQL> show user
            User is "TEST"


            SQL> select count(*) from test01$$;
              COUNT(*)
            ----------
            86968


            --将数据还原到test01表中
            SQL> insert into test01 select * from test01$$;


            --确认数据已经还原回来
            SQL> select count(*) from test01;


            COUNT(*)
            ----------
            86968

            经过测试,如果表被truncate后,未执行其它操作,数据可以使用fy_recover_data恢复回来。

            (2)使用fy_recover_data包执行truncate恢复,truncate后有新数据进入表(新插入的数据比truncate之前多)

            STEP1:创建测试表、序列、存储过程

              SQL> create table test01
              2 (
              3 col1 number,
              4 col2 number,
              5 col3 date,
              6 col4 varchar2(30),
              7 col5 varchar2(100)
                8  );
              Table created


              SQL> --创建自增序列
              SQL> CREATE SEQUENCE seq01
              2 START WITH 1
              3 MAXVALUE 99999999
              4 MINVALUE 0
              5 CYCLE
              6 CACHE 10
                7    ORDER;
              Sequence created

              SQL> --创建随机数据插入存储过程,其中col1列单调递增
              create or replace procedure p_insert_test01 IS
              v_col1 NUMBER;
              BEGIN
              FOR i IN 1..10000 LOOP
              select seq01.nextval INTO v_col1 from dual;
              insert into test01(col1,col2,col3,col4,col5)
              values
              (v_col1,
              (select round(dbms_random.value(10000, 100000000)) from dual),
              sysdate,
              (select dbms_random.string('a', 25) from dual),
              (select dbms_random.string('a', 85) from dual));
              END LOOP;
              commit;
              end p_insert_test01;

              STEP2:测试表插入10000条数据,col1列的值从1到10000,

                SQL> exec p_insert_test01;
                PL/SQL procedure successfully completed




                SQL> select count(*) from test01;
                COUNT(*)
                ----------
                10000



                SQL> SELECT MIN(col1),MAX(col1) FROM test01;
                MIN(COL1) MAX(COL1)
                ---------- ----------
                1 10000

                STEP3:执行truncate操作,

                  SQL> truncate table test01;
                  Table truncated

                  STEP4:接着往表里插入20000条数据,

                    SQL> exec p_insert_test01;
                    PL/SQL procedure successfully completed


                    SQL> exec p_insert_test01;
                    PL/SQL procedure successfully completed




                    SQL> select count(*) from test01;
                      COUNT(*)
                    ----------
                    20000



                    SQL> SELECT MIN(col1),MAX(col1) FROM test01;
                    MIN(COL1)  MAX(COL1)
                    ---------- ----------
                    10001 30000

                    STEP5:执行恢复操作,

                      [oracle@source-node ~]$ sqlplus as sysdba
                      SQL*Plus: Release 11.2.0.4.0 Production on Tue Apr 21 14:00:57 2020
                      Copyright (c) 1982, 2013, Oracle.  All rights reserved.
                      Connected to:
                      Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
                      With the Partitioning, OLAP, Data Mining and Real Application Testing options


                      SQL> set serveroutput on
                      SQL> set time on


                      14:01:09 SQL> exec fy_recover_data.recover_truncated_table('TEST','TEST01');
                      14:01:13: Use existing Directory Name: FY_DATA_DIR
                      14:01:13: Recover Table: TEST.TEST01$
                      14:01:14: Restore Table: TEST.TEST01$$
                      14:01:18: Copy file of Recover Tablespace: FY_REC_DATA_COPY.DAT1
                      14:01:18: begin to recover table TEST.TEST01
                      14:01:18: Use existing Directory Name: TMP_HF_DIR
                      14:01:18: Recovering data in datafile
                      /u01/app/oracle/oradata/testdb1/users01.dbf
                      14:01:18: Use existing Directory Name: TMP_HF_DIR
                      14:01:32: 402 truncated data blocks found.
                      14:01:32: 20000 records recovered in backup table TEST.TEST01$$
                      14:01:32: Total: 402 truncated data blocks found.
                      14:01:32: Total: 20000 records recovered in backup table TEST.TEST01$$
                      14:01:32: Recovery completed.
                      14:01:32: Data has been recovered to TEST.TEST01$$
                      PL/SQL procedure successfully completed.

                      STEP6:通过对test01$$表进行确认,发现返回的数据是truncate之后插入的数据,不符合要求。

                        SQL> select count(*) from test01;


                        COUNT(*)
                        ----------
                        20000
                        SQL> select count(*) from test01$$;


                        COUNT(*)
                        ----------
                        20000


                        SQL> SELECT MIN(col1),MAX(col1) FROM test01;


                        MIN(COL1) MAX(COL1)
                        ---------- ----------
                        10001 30000


                        SQL> SELECT MIN(col1),MAX(col1) FROM test01$$;


                        MIN(COL1) MAX(COL1)
                        ---------- ----------
                        10001 30000

                        (3)使用fy_recover_data包执行truncate恢复,truncate后有新数据进入表(新插入的数据比truncate之前少)。

                        STEP1:创建测试表、序列、存储过程,

                          SQL> DROP TABLE  test01 PURGE;
                          Table dropped


                          SQL> create table test01
                          2 (
                          3 col1 number,
                          4 col2 number,
                          5 col3 date,
                          6 col4 varchar2(30),
                          7 col5 varchar2(100)
                          8 );
                          Table created


                          SQL> DROP SEQUENCE seq01;
                          Sequence dropped


                          SQL> --创建自增序列
                          SQL> CREATE SEQUENCE seq01
                          2 START WITH 1
                          3 MAXVALUE 99999999
                          4 MINVALUE 0
                          5 CYCLE
                          6 CACHE 10
                          7 ORDER;
                          Sequence created


                          SQL> --创建随机数据插入存储过程,其中col1列单调递增
                          SQL> create or replace procedure p_insert_test01 IS
                          2 v_col1 NUMBER;
                          3 BEGIN
                          4 FOR i IN 1..10000 LOOP
                          5 select seq01.nextval INTO v_col1 from dual;
                          6 insert into test01(col1,col2,col3,col4,col5)
                          7 values
                          8 (v_col1,
                          9 (select round(dbms_random.value(10000, 100000000)) from dual),
                          10 sysdate,
                          11 (select dbms_random.string('a', 25) from dual),
                          12 (select dbms_random.string('a', 85) from dual));
                          13 END LOOP;
                          14 commit;
                          15 end p_insert_test01;
                          16  /


                          Procedure created

                          STEP2:测试表插入10000条数据,col1列的值从1到10000,

                            SQL> exec p_insert_test01;
                            PL/SQL procedure successfully completed




                            SQL> select count(*) from test01;
                              COUNT(*)
                            ----------
                            10000



                            SQL> SELECT MIN(col1),MAX(col1) FROM test01;
                            MIN(COL1)  MAX(COL1)
                            ---------- ----------
                            1 10000

                            STEP3:执行truncate操作,

                              SQL> truncate table test01;
                              Table truncated

                              STEP4:修改存储过程,酶促插入100条数据,

                                SQL> --创建随机数据插入存储过程,其中col1列单调递增
                                SQL> create or replace procedure p_insert_test01 IS
                                2 v_col1 NUMBER;
                                3 BEGIN
                                4 FOR i IN 1..100 LOOP
                                5 select seq01.nextval INTO v_col1 from dual;
                                6 insert into test01(col1,col2,col3,col4,col5)
                                7 values
                                8 (v_col1,
                                9 (select round(dbms_random.value(10000, 100000000)) from dual),
                                10 sysdate,
                                11 (select dbms_random.string('a', 25) from dual),
                                12 (select dbms_random.string('a', 85) from dual));
                                13 END LOOP;
                                14 commit;
                                15 end p_insert_test01;
                                16 /


                                Procedure created


                                -- 测试表插入100条数据
                                SQL> exec p_insert_test01;
                                PL/SQL procedure successfully completed

                                STEP5:执行恢复操作,

                                  [oracle@source-node ~]$ sqlplus as sysdba
                                  SQL*Plus: Release 11.2.0.4.0 Production on Tue Apr 21 14:22:34 2020
                                  Copyright (c) 1982, 2013, Oracle.  All rights reserved.
                                  Connected to:
                                  Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
                                  With the Partitioning, OLAP, Data Mining and Real Application Testing options


                                  SQL> set time on
                                  14:22:39 SQL> set serveroutput on
                                  14:22:44 SQL> exec fy_recover_data.recover_truncated_table('TEST','TEST01');
                                  14:22:52: Use existing Directory Name: FY_DATA_DIR
                                  14:22:52: Recover Table: TEST.TEST01$
                                  14:22:52: Restore Table: TEST.TEST01$$
                                  14:22:57: Copy file of Recover Tablespace: FY_REC_DATA_COPY.DAT1
                                  14:22:57: begin to recover table TEST.TEST01
                                  14:22:57: Use existing Directory Name: TMP_HF_DIR
                                  14:22:57: Recovering data in datafile
                                  /u01/app/oracle/oradata/testdb1/users01.dbf
                                  14:22:57: Use existing Directory Name: TMP_HF_DIR
                                  14:23:06: 5 truncated data blocks found.
                                  14:23:06: 100 records recovered in backup table TEST.TEST01$$
                                  14:23:06: Total: 5 truncated data blocks found.
                                  14:23:06: Total: 100 records recovered in backup table TEST.TEST01$$
                                  14:23:06: Recovery completed.
                                  14:23:06: Data has been recovered to TEST.TEST01$$


                                  PL/SQL procedure successfully completed.

                                  STEP6:通过对test01$$表进行确认,发现返回的数据是truncate之后插入的数据,不符合要求。

                                    SQL> select count(*) from test01;
                                      COUNT(*)
                                    ----------
                                    100


                                    SQL> SELECT MIN(col1),MAX(col1) FROM test01;
                                    MIN(COL1)  MAX(COL1)
                                    ---------- ----------
                                    10001 10100


                                    SQL> select count(*) from test01$$;
                                      COUNT(*)
                                    ----------
                                    100


                                    SQL> SELECT MIN(col1),MAX(col1) FROM test01$$;
                                    MIN(COL1)  MAX(COL1)
                                    ---------- ----------
                                    10001 10100

                                    (4)测试数据文件被覆盖是否影响恢复。

                                    STEP1:创建测试表,

                                      SQL> create table test01
                                      2 (
                                      3 col1 number,
                                      4 col2 number,
                                      5 col3 date,
                                      6 col4 varchar2(30),
                                      7 col5 varchar2(100)
                                      8 ) TABLESPACE USERS;
                                      Table created

                                      STEP2:初始时候,表空间总共20MB,剩余15.94MB,

                                        SQL> SELECT SUBSTR(a.TABLESPACE_NAME,1,30) TablespaceName,
                                        2 round(SUM(a.bytes/1024/1024),2) AS "Totle_size(MB)",
                                        3 round(SUM(NVL(b.free_space1/1024/1024,0)),2) AS "Free_space(MB)",
                                        4 round(SUM(a.bytes/1024/1024),2)-round(SUM(NVL(b.free_space1/1024/1024,0)),2) AS "Used_space(MB)",
                                        5 ROUND((SUM(a.bytes/1024/1024)-SUM(NVL(b.free_space1/1024/1024,0))) *100/SUM(a.bytes/1024/1024),2) AS "Used_percent%",
                                        6 round(SUM((case when a.MAXBYTES = 0 then a.bytes else a.MAXBYTES end)/1024/1024),2) AS "Max_size(MB)",
                                        7 ROUND((SUM(a.bytes/1024/1024)-SUM(NVL(b.free_space1/1024/1024,0)))*100/SUM((case when a.MAXBYTES = 0 then a.bytes else a.MAXBYTES end)/1024/1024),2) AS "Max_percent%"
                                        8 FROM dba_data_files a,
                                        9 (SELECT SUM(NVL(bytes,0)) free_space1,
                                        10 file_id
                                        11 FROM dba_free_space
                                        12 GROUP BY file_id
                                        13 ) b
                                        14 WHERE a.file_id = b.file_id(+)
                                        15 AND a.TABLESPACE_NAME = 'USERS'
                                        16 GROUP BY a.TABLESPACE_NAME;


                                        TABLESPACENAME     Totle_size(MB) Free_space(MB) Used_space(MB) Used_percent% Max_size(MB) Max_percent%
                                        ------------------ -------------- -------------- -------------- ------------- ------------ ------------
                                        USERS               20             15.94          4.06           20.31         20         20.31

                                        STEP3:test01表插入大量数据,

                                          SQL> exec p_insert_test01;
                                          PL/SQL procedure successfully completed


                                          SQL>
                                          PL/SQL procedure successfully completed


                                          SQL>
                                          PL/SQL procedure successfully completed


                                          SQL>
                                          PL/SQL procedure successfully completed


                                          SQL>
                                          PL/SQL procedure successfully completed


                                          SQL>
                                          PL/SQL procedure successfully completed


                                          SQL>
                                          PL/SQL procedure successfully completed


                                          SQL>
                                          PL/SQL procedure successfully completed


                                          SQL> /
                                          PL/SQL procedure successfully completed


                                          SQL> /
                                          begin p_insert_test01; end;


                                          ORA-01653: unable to extend table TEST.TEST01 by 128 in tablespace USERS
                                          ORA-06512: at "TEST.P_INSERT_TEST01", line 6
                                          ORA-06512: at line 1

                                          STEP4:此时,表空间总共20MB,剩余0.94MB,

                                            SQL> SELECT SUBSTR(a.TABLESPACE_NAME,1,30) TablespaceName,
                                            2 round(SUM(a.bytes/1024/1024),2) AS "Totle_size(MB)",
                                            3 round(SUM(NVL(b.free_space1/1024/1024,0)),2) AS "Free_space(MB)",
                                            4 round(SUM(a.bytes/1024/1024),2)-round(SUM(NVL(b.free_space1/1024/1024,0)),2) AS "Used_space(MB)",
                                            5 ROUND((SUM(a.bytes/1024/1024)-SUM(NVL(b.free_space1/1024/1024,0))) *100/SUM(a.bytes/1024/1024),2) AS "Used_percent%",
                                            6 round(SUM((case when a.MAXBYTES = 0 then a.bytes else a.MAXBYTES end)/1024/1024),2) AS "Max_size(MB)",
                                            7 ROUND((SUM(a.bytes/1024/1024)-SUM(NVL(b.free_space1/1024/1024,0)))*100/SUM((case when a.MAXBYTES = 0 then a.bytes else a.MAXBYTES end)/1024/1024),2) AS "Max_percent%"
                                            8 FROM dba_data_files a,
                                            9 (SELECT SUM(NVL(bytes,0)) free_space1,
                                            10 file_id
                                            11 FROM dba_free_space
                                            12 GROUP BY file_id
                                            13 ) b
                                            14 WHERE a.file_id = b.file_id(+)
                                            15 AND a.TABLESPACE_NAME = 'USERS'
                                            16 GROUP BY a.TABLESPACE_NAME;


                                            TABLESPACENAME    Totle_size(MB) Free_space(MB) Used_space(MB) Used_percent% Max_size(MB) Max_percent%
                                            ----------------- -------------- -------------- -------------- ------------- ------------ ------------
                                            USERS              20             0.94           19.06          95.31         20         95.31

                                            STEP5:此时test01表有90000行数据,

                                              SQL> select count(*) from test01;
                                                COUNT(*)
                                              ----------
                                              90000


                                              SQL> SELECT MIN(col1),MAX(col1) FROM test01;
                                              MIN(COL1)  MAX(COL1)
                                              ---------- ----------
                                              109751 199750

                                              STEP6:对test01执行truncate,

                                                SQL> truncate table test01;
                                                Table truncated

                                                STEP7:执行truncate后,空间已经释放,

                                                  SQL> SELECT SUBSTR(a.TABLESPACE_NAME,1,30) TablespaceName,
                                                  2 round(SUM(a.bytes/1024/1024),2) AS "Totle_size(MB)",
                                                  3 round(SUM(NVL(b.free_space1/1024/1024,0)),2) AS "Free_space(MB)",
                                                  4 round(SUM(a.bytes/1024/1024),2)-round(SUM(NVL(b.free_space1/1024/1024,0)),2) AS "Used_space(MB)",
                                                  5 ROUND((SUM(a.bytes/1024/1024)-SUM(NVL(b.free_space1/1024/1024,0))) *100/SUM(a.bytes/1024/1024),2) AS "Used_percent%",
                                                  6 round(SUM((case when a.MAXBYTES = 0 then a.bytes else a.MAXBYTES end)/1024/1024),2) AS "Max_size(MB)",
                                                  7 ROUND((SUM(a.bytes/1024/1024)-SUM(NVL(b.free_space1/1024/1024,0)))*100/SUM((case when a.MAXBYTES = 0 then a.bytes else a.MAXBYTES end)/1024/1024),2) AS "Max_percent%"
                                                  8 FROM dba_data_files a,
                                                  9 (SELECT SUM(NVL(bytes,0)) free_space1,
                                                  10 file_id
                                                  11 FROM dba_free_space
                                                  12 GROUP BY file_id
                                                  13 ) b
                                                  14 WHERE a.file_id = b.file_id(+)
                                                  15 AND a.TABLESPACE_NAME = 'USERS'
                                                  16 GROUP BY a.TABLESPACE_NAME;


                                                  TABLESPACENAME    Totle_size(MB) Free_space(MB) Used_space(MB) Used_percent% Max_size(MB) Max_percent%
                                                  ----------------- -------------- -------------- -------------- ------------- ------------ ------------
                                                  USERS              20             15.88          4.12           20.63         20         20.63

                                                  STEP8:创建表test02,用来覆盖test01释放的空间,

                                                    SQL> create table test02 as select * from dba_objects;
                                                    Table created

                                                    STEP9:test02表创建之后,剩余空间为5.88MB,可以说明:test02表的数据占用了test01表释放出来的空间,即test01表的部分数据已经被覆盖。

                                                      SQL> SELECT SUBSTR(a.TABLESPACE_NAME,1,30) TablespaceName,
                                                      2 round(SUM(a.bytes/1024/1024),2) AS "Totle_size(MB)",
                                                      3 round(SUM(NVL(b.free_space1/1024/1024,0)),2) AS "Free_space(MB)",
                                                      4 round(SUM(a.bytes/1024/1024),2)-round(SUM(NVL(b.free_space1/1024/1024,0)),2) AS "Used_space(MB)",
                                                      5 ROUND((SUM(a.bytes/1024/1024)-SUM(NVL(b.free_space1/1024/1024,0))) *100/SUM(a.bytes/1024/1024),2) AS "Used_percent%",
                                                      6 round(SUM((case when a.MAXBYTES = 0 then a.bytes else a.MAXBYTES end)/1024/1024),2) AS "Max_size(MB)",
                                                      7 ROUND((SUM(a.bytes/1024/1024)-SUM(NVL(b.free_space1/1024/1024,0)))*100/SUM((case when a.MAXBYTES = 0 then a.bytes else a.MAXBYTES end)/1024/1024),2) AS "Max_percent%"
                                                      8 FROM dba_data_files a,
                                                      9 (SELECT SUM(NVL(bytes,0)) free_space1,
                                                      10 file_id
                                                      11 FROM dba_free_space
                                                      12 GROUP BY file_id
                                                      13 ) b
                                                      14 WHERE a.file_id = b.file_id(+)
                                                      15 AND a.TABLESPACE_NAME = 'USERS'
                                                      16 GROUP BY a.TABLESPACE_NAME;


                                                      TABLESPACENAME   Totle_size(MB) Free_space(MB) Used_space(MB) Used_percent% Max_size(MB) Max_percent%
                                                      ---------------- -------------- -------------- -------------- ------------- ------------ ------------
                                                      USERS             20             5.88           14.12          70.63         20         70.63

                                                      STEP10:执行恢复操作,

                                                        [oracle@source-node ~]$ sqlplus / as sysdba
                                                        SQL*Plus: Release 11.2.0.4.0 Production on Tue Apr 21 15:09:58 2020
                                                        Copyright (c) 1982, 2013, Oracle.  All rights reserved.
                                                        Connected to:
                                                        Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
                                                        With the Partitioning, OLAP, Data Mining and Real Application Testing options


                                                        SQL> set time on
                                                        15:10:05 SQL> set serveroutput on
                                                        15:10:10 SQL> exec fy_recover_data.recover_truncated_table('LIJIAMAN','TEST01');
                                                        15:10:17: Use existing Directory Name: FY_DATA_DIR
                                                        15:10:17: Recover Table: LIJIAMAN.TEST01$
                                                        15:10:17: Restore Table: LIJIAMAN.TEST01$$
                                                        15:10:22: Copy file of Recover Tablespace: FY_REC_DATA_COPY.DAT1
                                                        15:10:22: begin to recover table LIJIAMAN.TEST01
                                                        15:10:22: Use existing Directory Name: TMP_HF_DIR
                                                        15:10:22: Recovering data in datafile
                                                        /u01/app/oracle/oradata/testdb1/users01.dbf
                                                        15:10:22: Use existing Directory Name: TMP_HF_DIR
                                                        15:10:31: 645 truncated data blocks found.
                                                        15:10:31: 24439 records recovered in backup table LIJIAMAN.TEST01$$
                                                        15:10:31: Total: 645 truncated data blocks found.
                                                        15:10:31: Total: 24439 records recovered in backup table LIJIAMAN.TEST01$$
                                                        15:10:31: Recovery completed.
                                                        15:10:31: Data has been recovered to LIJIAMAN.TEST01$$


                                                        PL/SQL procedure successfully completed.

                                                        STEP11:发现只恢复了部分数据,不符合要求,

                                                          -- truncate之前test01表有90000行数据,恢复了24339行数据
                                                          SQL> select count(*) from test01$$;
                                                            COUNT(*)
                                                          ----------
                                                          24439


                                                          SQL> SELECT MIN(col1),MAX(col1) FROM test01$$;
                                                          MIN(COL1)  MAX(COL1)
                                                          ---------- ----------
                                                          109751 199750

                                                          因此,使用工具fy_recover_data进行数据恢复,需要确认,

                                                          (1)truncate之后,需要保证没有新的数据进入表中,否则无法还原;

                                                          (2)存放该表的数据文件块不能被覆盖,否则无法完整还原数据。

                                                          在发生故障后,可以迅速使用,

                                                            SQL> alter tablespace users read only;
                                                            SQL> alter tablespace users read write;

                                                            来关闭/开启表空间的写功能,这样可以保证数据文件不会被覆写。

                                                            参考,https://www.modb.pro/db/32403?utm_source=index_aihttps://www.cnblogs.com/lijiaman/p/12747658.html

                                                            如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,

                                                            近期更新的文章:《MySQL创建内部临时表的场景》《我国法律位阶的学习和了解》《金融知识小科普 - 多层次资本市场》《如何定位锁定用户的元凶?》
                                                            《数据库干货硬核公众号》
                                                            近期的热文:《推荐一篇Oracle RAC Cache Fusion的经典论文》
                                                            《"红警"游戏开源代码带给我们的震撼》
                                                            文章分类和索引:《公众号1300篇文章分类和索引》

                                                            相关文章

                                                            Oracle如何使用授予和撤销权限的语法和示例
                                                            Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
                                                            下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
                                                            社区版oceanbase安装
                                                            Oracle 导出CSV工具-sqluldr2
                                                            ETL数据集成丨快速将MySQL数据迁移至Doris数据库

                                                            发布评论