咨询微信: dbservice1234 7 x 24 在线支持!

Oracle 当一个或多个数据文件丢失时如何从表空间中恢复数据

Oracle 当一个或多个数据文件丢失时如何从表空间中恢复数据

如果自己搞不定可以找诗檀软件专业ORACLE数据库修复团队成员帮您恢复!

诗檀软件专业数据库修复团队

服务热线 : 13764045638 QQ号:47079569 邮箱:service@parnassusdata.com

 

 

 

目的

-------

 本文针对从部分可用的表空间中获取数据,以及以下恢复选项不可用的情况。

 

 . 表空间/数据文件媒体恢复选项失败或不可用。

 . 无法替换用户或使用Application操作,由于:

   - 最近的export dump不可用

   - 使用脚本或通过SQL*Loader无法重新填充表

 

本文描述的步骤仅适用于字典管理的表空间。

 

 

范围 & 应用

-------------------

 当无法应用正常备份和恢复场景,需要恢复尽可能多的数据的Oracle 数据库管理员。

 

 在数据库在noarchivelog 模式下运行且属于一个用户表空间的一个或多个数据文件在操作系统级别丢失的情况下,你需要按照本文来操作。

 - 或 -

 archivelog 数据库没有可用的丢失数据文件的备份或必要的重做。

 

 

如果从一个或多个数据文件丢失的部分可用的表空间中恢复数据。

----------------------------------------------------------------------------------------------

 

 对引用(多个)数据文件的对象的任意操作会失败并显示:

 

  ORA-01116: error in opening database file 5

  ORA-01110: data file 5: '/u01/oradata/V817/data/users02.dbf'

  ORA-27041: unable to open file

 

 在没有drop整个表空间的情况下,无法从表空间中删除eliminate单个丢失文件来解决问题。

 但首先我们可以尝试尽可能多得恢复数据。

 

1. 识别(多个)丢失数据文件的文件号:

 

     SQL> select relative_fno, file_name

          from dba_data_files

          where tablespace_name = '_tablespace_name_';

    

       RELATIVE_FNO FILE_NAME

     -------------- --------------------------------------

                  4 /u01/oradata/V817/data/users01.dbf

   =>             5 /u01/oradata/V817/data/users02.dbf

                  6 /u01/oradata/V817/data/users03.dbf

 

 

2. 在表空间中没有在丢失数据文件中分配extent的对象,可以简单地使用各种方法来重建:

 

     - alter table X move tablespace Y

       alter index X rebuild tablespace Y

     - table export/import

     - create table X as select ...

 

   你需要确定在表空间中哪些数据段没有被分配到丢失数据文件的extent,然后使用上述技巧之一重建它们:

 

     SQL> select distinct owner, segment_name, segment_type

          from dba_extents

          where tablespace_name = '_tablespace_name_'

            and relative_fno NOT IN (file number(s) of missing datafile(s) noted in point 1);

 

     OWNER        SEGMENT_NAME         SEGMENT_TYPE

     ------------ -------------------- --------------------

     SCOTT      DEPT                 TABLE

     SCOTT       EMP                  TABLE

     ...

 

 

3.在丢失的(多个)数据文件中分配了一个或多个extent的表空间对象不能简单地被重建,因为访问它们的尝试都将导致ORA-1116。请注意,在分配到丢失数据文件的extent中的数据都将丢失且无法以任何方式恢复。因此,要恢复在这些数据段的其他数据,可以进行以下操作。

 

  3.1 确定哪些数据段的extent分配到(多个)丢失的数据文件:

 

      SQL> select distinct owner, segment_name, segment_type, partition_name

           from dba_extents

           where relative_fno IN (file number(s) of missing datafile(s) noted in point 1);

 

      OWNER      SEGMENT_NAME      SEGMENT_TYPE          PARTITION_NAME

      ------------ -------------------- --------------------  -----------------

      SCOTT        BONUS                TABLE

      SCOTT        PART_TEST            TABLE PARTITION       PART_TEST_P2

    

      注意你需要对以上列表中返回的每个对象重复3.2到3.4的步骤。

 

 

  3.2 然后,我们需要检索这些数据段的extent布局。如果有问题的数据段是reguluar表,那么你需要运行的第一个查询。如果是分区表,那么你需要运行第二个查询:

 

     

      SQL> select e.segment_name, o.data_object_id, e.relative_fno, e.block_id, e.blocks

           from dba_extents e, dba_objects o

           where o.owner = e.owner

             and o.object_name = e.segment_name

             and e.owner = 'SCOTT'

             and e.segment_name = 'BONUS'

             and e.relative_fno IN (file number(s) of missing datafile(s) noted in point 1)

           order by e.relative_fno, o.data_object_id, e.block_id;

 

      SEGMENT_NAME        DATA_OBJECT_ID RELATIVE_FNO   BLOCK_ID     BLOCKS

      ------------------- -------------- ------------ ---------- ----------

      BONUS                        24532            5         34         10

      BONUS                        24532            5         44         10

      BONUS                        24532            5         54         10

 

 

     

      SQL> select e.segment_name, e.partition_name, o.data_object_id, e.relative_fno, e.block_id, e.blocks

           from dba_extents e,dba_objects o

           where o.owner = e.owner

             and o.object_name = e.segment_name

             and o.subobject_name = e.partition_name

             and e.owner = 'SCOTT'

             and e.segment_name = 'PART_TEST'

             and e.relative_fno IN (file number(s) of missing datafile(s) noted in point 1)

           order by e.relative_fno, o.data_object_id, e.block_id;

 

      SEGMENT_NAME    PARTITION_NAME         DATA_OBJECT_ID RELATIVE_FNO BLOCK_ID   BLOCKS

      --------------- ---------------------- -------------- ------------ -------- --------

      PART_TEST       PART_TEST_P2                    30130            5      137      128

      PART_TEST       PART_TEST_P2                    30130            5      265      128

      PART_TEST       PART_TEST_P2                    30130            5      393      128

      PART_TEST       PART_TEST_P2                    30130            5      521      128

 

 

  3.3 使用以上信息,我们可以创建需要排除的rowid。这可以通过使用DBMS_ROWID.ROWID_CREATE功能来实现:

 

        Specification: 

          function rowid_create(rowid_type    IN number,

                                object_number IN number,

                                relative_fno  IN number,

                                block_number  IN number,

                                row_number    IN number)

         return rowid;

 

        Description:

          rowid_type    - type (restricted/extended)

          object_number - data object number (rowid_object_undefined for restricted)

          relative_fno  - relative file number

          block_number  - block number in this file

          file_number   - file number in this block

 

      使用该对象的最低block_id可以构建rowid的下限:

 

        SQL> select dbms_rowid.rowid_create(1,24532,5,34,0) low_rid from dual;

 

        LOW_RID

        ------------------

        AAAF/UAAFAAAAAiAAA

 

      使用最高block_id + 块数 + 1块,可以构建rowid的上限,因为我们不知道在最后的块中会有多少行:(54 + 10 + 1 = 65)。

 

        SQL> select dbms_rowid.rowid_create(1,24532,5,65,0) high_rid from dual;

 

        HIGH_RID

        ------------------

        AAAF/UAAFAAAABBAAA

 

 

  3.4 最后,可以使用CREATE TABLE AS SELECT 或/和 INSERT ... SELECT来检索数据而无需访问丢失数据文件中的块:

 

        SQL> create table salvage_bonus as

             select /*+ ROWID(A) */ *

             from  A

                  where rowid < '_low_rid_';

 

         SQL> insert into salvage_bonus

             select /*+ ROWID(A) */ *

             from  A

              where rowid >= '_high_rid_';

 

 

4. 在表空间中所有对象被抽取后,drop表空间。

 

     SQL> drop tablespace _tablespace_name_ including contents;

 

 

5. Recreate 重建表空间并rebuild将所有对象重建,移到到新的表空间。

   请注意如果所有对象已在数据库中重建并移到到另一个表空间中,这个最后步骤就可以跳过。

 

 

相关文档

-----------------

 Note 61685.1  Extracting Data from a Corrupt Table using ROWID Range Scans in Oracle8/8i