HelloDBA [English]
搜索Internet 搜索 HelloDBABA
  Oracle技术站。email: fuyuncat@gmail.com  MSN: fuyuncat@hotmail.com   acoug  acoug 

偷梁换柱——极端情况下的数据拯救(一)

[English]

作者: fuyuncat

来源: www.HelloDBA.com

日期: 2013-03-19 09:45:41

分享到  新浪微博 腾讯微博 人人网 i贴吧 开心网 豆瓣 淘宝 推特 Facebook GMail Blogger Orkut Google Bookmarks

 要保证数据安全,需要做好完整的数据备份恢复计划及容灾方案。在实际环境中,还是有很多数据库环境没有做到这些,并且出现一些灾难性的错误,例如Online Redo或者控制文件等重要文件损坏或丢失。发生这种错误时,往往常规的恢复手段无法找回数据,可能需要借助隐含参数、BBED甚至Dul工具进行数据挽救。那么我们就面临这样的问题:在什么样的最极端情况下,我们还能挽救回数据呢?理论上讲,我们的数据包含两个最基本的部分:即数据定义(也就是元数据)部分及数据主体部分。我们的用户数据存储在相应表空间的数据文件当中,而元数据部分则存储在系统表空间的数据文件当中。那么,假如进存在系统表空间及重要数据文件(而非所有数据文件)的情况下还有希望恢复数据吗?当然,这里不讨论使用Dul的方式进行回复。

就这个问题,我做了两个测试,一个是在Windows的11.2.0.1的环境中,一个是在Linux的10.2.0.1的环境当中。

首先,我们需要知道,除了数据本身之外,我们还需要知道那些信息才能进行恢复:

 

  •   数据库版本及其所处平台、CPU位数
  •   数据库名称
  •   数据块大小
  •   字符集
  •   原始的数据文件位置及大小

 

以上信息基本上我们可以通过其他途径获取,例如客户端的配置。

获取到以上信息后,我们可以理清一下恢复的思路:

 

  1.   在与原环境基本一致的新环境中,创建一个同名的新数据库;
  2.   将新的系统文件替换为旧的系统文件;
  3.   修改旧的系统文件元数据,使其与新数据库匹配;
  4.   重新加载数据库后,再将用户数据文件植入
  5.   重命名数据文件,并使其ONLINE
  6.   用EXP方式导出数据

 

可以看到,以上几个步骤当中,最关键的是第三步。如果旧的系统文件被“偷梁换柱”置入新数据库中,那么旧数据库中的对象元数据也被带入了新的数据库当中。

以下过程为在Windows的11.2.0.1的环境中测试过程:

首先,配置参数文件。注意UNDO管理方式设为手动,因为旧数据库中UNDO文件已经丢失;_allow_resetlogs_corruption也要打开,因为新数据库中ONLINE REDO信息无法与旧数据库中的数据文件匹配:

SQL代码
  1. _allow_resetlogs_corruption = true  
  2. control_files              = (E:\ora11gr1\oradata\ORA11R2\control01.ctl,  
  3.                               E:\ora11gr1\oradata\ORA11R2\control02.ctl,  
  4.                               E:\ora11gr1\oradata\ORA11R2\control03.ctl)  
  5. db_name                    = ORA11R2  
  6. db_domain                  = ""  
  7. db_block_size              = 8192  
  8. undo_management            = manual  
  9. undo_tablespace            = ''  
  10. UNDO_RETENTION             = 900  
  11. nls_language               = "AMERICAN"  
  12. nls_territory              = "AMERICA"  

然后需要配置SID,设置密码,并启动window服务

SQL代码
  1. set ORACLE_SID=ora11r2  
  2.   
  3. E:\>cd E:\ora11gr1\product\11.2.0\dbhome_1\database  
  4.   
  5. E:\ora11gr1\product\11.2.0\dbhome_1\database>orapwd password=sys file=PWDORA11R2.ORA  
  6.   
  7. E:\ora11gr1\product\11.2.0\dbhome_1\database>oradim -startup -sid ORA11R2  

现在可以建立新库:

SQL代码
  1. HELLODBA.COM>startup nomount  
  2. ORACLE instance started.  
  3.   
  4. Total System Global Area  150667264 bytes  
  5. Fixed Size                  1373152 bytes  
  6. Variable Size              92277792 bytes  
  7. Database Buffers           50331648 bytes  
  8. Redo Buffers                6684672 bytes  
  9. HELLODBA.COM>CREATE DATABASE ORA11R2  
  10.   2     USER SYS IDENTIFIED BY sys  
  11.   3     USER SYSTEM IDENTIFIED BY oracle  
  12.   4     LOGFILE GROUP 1 ('E:\ora11gr1\oradata\ORA11R2\redo01.log'SIZE 20M,  
  13.   5             GROUP 2 ('E:\ora11gr1\oradata\ORA11R2\redo02.log'SIZE 20M,  
  14.   6             GROUP 3 ('E:\ora11gr1\oradata\ORA11R2\redo03.log'SIZE 20M  
  15.   7     MAXLOGFILES 5  
  16.   8     MAXLOGMEMBERS 5  
  17.   9     MAXLOGHISTORY 1  
  18.  10     MAXDATAFILES 100  
  19.  11     MAXINSTANCES 1  
  20.  12     CHARACTER SET US7ASCII  
  21.  13     NATIONAL CHARACTER SET AL16UTF16  
  22.  14     DATAFILE 'E:\ora11gr1\oradata\ORA11R2\system01.dbf' SIZE 740M REUSE  
  23.  15     EXTENT MANAGEMENT LOCAL  
  24.  16     SYSAUX DATAFILE 'E:\ora11gr1\oradata\ORA11R2\sysaux01.dbf' SIZE 100M  
  25.  17     DEFAULT TEMPORARY TABLESPACE tempts1  
  26.  18        TEMPFILE 'E:\ora11gr1\oradata\ORA11R2\temp01.dbf'  
  27.  19        SIZE 20M  
  28.  20  ;  
  29.   
  30. Database created.  
  31.   
  32. HELLODBA.COM>shutdown  
  33. Database closed.  
  34. Database dismounted.  
  35. ORACLE instance shut down.  
  36. HELLODBA.COM>exit  

重命名新库的系统文件,因为我们还需要它的文件头信息。拷贝旧库中文件到当前文件路径下:

SQL代码
  1. E:\ora11gr1\oradata\ORA11R2>rename SYSTEM01.DBF SYSTEM01_NEW.DBF  
  2.   
  3. E:\ora11gr1\oradata\ORA11R2>copy ..\ORA11R2_COPY\SYSTEM01.DBF  
  4. 已复制         1 个文件。  
  5.   
  6. E:\ora11gr1\oradata\ORA11R2>copy ..\ORA11R2_COPY\DEMO_DATA.DBF  
  7. 已复制         1 个文件。  

利用工具,将新库系统文件的文件头部分拷贝到旧库的文件头。这里我们利用BBED拷贝(11g当中,bbed的2号数据块实际为1号数据块)

SQL代码
  1. D:\OracleDoc\bbed9i>bbed parfile=bbed.par  
  2.   
  3. BBED: Release 2.0.0.0.0 - Limited Production on Fri Mar 8 14:30:31 2013  
  4.   
  5. Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.  
  6.   
  7. ************* !!! For Oracle Internal Use only !!! ***************  
  8.   
  9. BBED> info  
  10.  File#  Name                                                        Size(blks)  
  11.  -----  ----                                                        ----------  
  12.     17  E:\Ora11gr1\Oradata\ORA11R2\SYSTEM01_NEW.DBF                     94721  
  13.     18  E:\Ora11gr1\Oradata\ORA11R2\SYSTEM01.DBF                         94721  
  14. BBED> copy file 17 block 2 file 18 block 2  
  15. Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y  
  16.  File: E:\Ora11gr1\Oradata\ORA11R2\CONTROL01.CTL (1)  
  17.  Block: 1                Offsets:    0 to  511           Dba:0x00400001  
  18. ------------------------------------------------------------------------  
  19.  0ba20000 01004000 00000000 00000104 d4540000 00000000 0000200b bda06372  

然后利用NID修改数据库ID

SQL代码
  1. HELLODBA.COM>startup mount  
  2. ORACLE instance started.  
  3.   
  4. Total System Global Area  150667264 bytes  
  5. Fixed Size                  1373152 bytes  
  6. Variable Size              92277792 bytes  
  7. Database Buffers           50331648 bytes  
  8. Redo Buffers                6684672 bytes  
  9. Database mounted.  
  10. HELLODBA.COM>exit  
  11.   
  12. C:\Users\huanged>nid target=sys/sys   

注意:第一次执行时,可能会出现ORA-00600错误

SQL代码
  1. ORA-00600: internal error code, arguments: [krbnpdf_wrngdbid_3], [E:\ORA11GR1\ORADATA\ORA11R  
  2. 01.DBF], [1919131837], [1935277929], [1935311342], [], [], [], [], [], [], []  
  3. ORA-06512: at "SYS.X$DBMS_BACKUP_RESTORE", line 6848  
  4. ORA-06512: at line 1  

这种情况下,再次执行nid

SQL代码
  1. C:\Users\huanged>nid target=sys/sys   
  2.   
  3. DBNEWID: Release 11.2.0.1.0 - Production on Fri Mar 8 13:56:35 2013  
  4. ... ...  
  5. Database ID for database ORA11R2 changed to 1919131837.  
  6. All previous backups and archived redo logs for this database are unusable.  
  7. Database has been shutdown, open database with RESETLOGS option.  
  8. Succesfully changed database ID.  
  9. DBNEWID - Completed succesfully.  

我们可以做一次verification,确认系统文件没有错误

SQL代码
  1. C:\Users\huanged>dbv file=E:\Ora11gr1\Oradata\ORA11R2\SYSTEM01.DBF  
  2.   
  3. DBVERIFY: Release 11.2.0.1.0 - Production on Fri Mar 8 13:59:46 2013  
  4.   
  5. Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.  
  6.   
  7. DBVERIFY - Verification starting : FILE = E:\ORA11GR1\ORADATA\ORA11R2\SYSTEM01.DBF  
  8.   
  9.   
  10. DBVERIFY - Verification complete  
  11.   
  12. Total Pages Examined         : 94720  
  13. Total Pages Processed (Data) : 64118  
  14. Total Pages Failing   (Data) : 0  
  15. Total Pages Processed (Index): 13493  
  16. Total Pages Failing   (Index): 0  
  17. Total Pages Processed (Other): 3870  
  18. Total Pages Processed (Seg)  : 1  
  19. Total Pages Failing   (Seg)  : 0  
  20. Total Pages Empty            : 13239  
  21. Total Pages Marked Corrupt   : 0  
  22. Total Pages Influx           : 0  
  23. Total Pages Encrypted        : 0  
  24. Highest block SCN            : 4072482757 (0.4072482757)  

然后重建控制文件,并且OPEN RESETLOGS

SQL代码
  1. HELLODBA.COM>startup nomount  
  2. ORACLE instance started.  
  3.   
  4. Total System Global Area  150667264 bytes  
  5. Fixed Size                  1373152 bytes  
  6. Variable Size              92277792 bytes  
  7. Database Buffers           50331648 bytes  
  8. Redo Buffers                6684672 bytes  
  9.   
  10. HELLODBA.COM>CREATE CONTROLFILE REUSE DATABASE ORA11R2 RESETLOGS NOARCHIVELOG  
  11.   2      MAXLOGFILES 5  
  12.   3      MAXLOGMEMBERS 5  
  13.   4      MAXDATAFILES 100  
  14.   5      MAXINSTANCES 1  
  15.   6      MAXLOGHISTORY 292  
  16.   7  LOGFILE  
  17.   8    GROUP 1 'E:\ORA11GR1\ORADATA\ORA11R2\REDO01.LOG' SIZE 20M BLOCKSIZE 512,  
  18.   9    GROUP 2 'E:\ORA11GR1\ORADATA\ORA11R2\REDO02.LOG' SIZE 20M BLOCKSIZE 512,  
  19.  10    GROUP 3 'E:\ORA11GR1\ORADATA\ORA11R2\REDO03.LOG' SIZE 20M BLOCKSIZE 512  
  20.  11  DATAFILE  
  21.  12    'E:\ORA11GR1\ORADATA\ORA11R2\SYSTEM01.DBF' SIZE 740M  
  22.  13    --, 'E:\ORA11GR1\ORADATA\ORA11R2\SYSAUX01.DBF' size 100M  
  23.  14    --, 'E:\ORA11GR1\ORADATA\ORA11R2\UNDOTBS01.DBF'  
  24.  15  CHARACTER SET US7ASCII  
  25.  16  ;  
  26.   
  27. Control file created.  
  28.   
  29. HELLODBA.COM>alter session set events '10046 trace name context forever, level 12';  
  30.   
  31. Session altered.  
  32.   
  33. HELLODBA.COM>recover database using backup controlfile until cancel;  
  34. ORA-00279: change 4072482761 generated at 03/07/2013 09:28:18 needed for thread 1  
  35. ORA-00289: suggestion : E:\ORA11GR1\PRODUCT\11.2.0\DBHOME_1\RDBMS\ARC0000000215_0793385284.0001  
  36. ORA-00280: change 4072482761 for thread 1 is in sequence #215  
  37.   
  38.   
  39. Specify log: {<RET>=suggested | filename | AUTO | CANCEL}  
  40. cancel  
  41. Media recovery cancelled.  
  42. HELLODBA.COM>alter database open resetlogs;  
  43.   
  44. Database altered.  

如果此时数据库OPEN成功,那离我们的目标就非常接近了

查询用户数据文件在旧库中的文件号,此时应该可以读取到旧中的数据字典了(注意,我们建立新库时,并未创建相关视图及存储过程,这里读取的视图就是旧库中的视图)。从文件名可以猜测出其表空间的名称:

SQL代码
  1. HELLODBA.COM>select file_id, tablespace_name from dba_data_files where tablespace_name like '%DEMO%';  
  2.   
  3.    FILE_ID TABLESPACE_NAME  
  4. ---------- ------------------------------  
  5.          5 DEMO_DATA  
  6.          6 DEMO_INDX  
  7.   
  8. HELLODBA.COM>select file#, name from v$datafile where file#=5;  
  9.   
  10.      FILE# NAME  
  11. ---------- -----------------------------------------------------------------  
  12.          5 E:\ORA11GR1\PRODUCT\11.2.0\DBHOME_1\DATABASE\MISSING00005  

重命名数据文件,并且将其重新ONLINE

SQL代码
  1. HELLODBA.COM>ALTER DATABASE RENAME FILE 'E:\ORA11GR1\PRODUCT\11.2.0\DBHOME_1\DATABASE\MISSING00005' TO 'E:\ORA11GR1\ORADATA\ORA11R2\DEMO_DATA.DBF';  
  2.   
  3. Database altered.  
  4.   
  5. HELLODBA.COM>shutdown  
  6. Database closed.  
  7. Database dismounted.  
  8. ORACLE instance shut down.  
  9. HELLODBA.COM>startup mount  
  10. ORACLE instance started.  
  11.   
  12. Total System Global Area  150667264 bytes  
  13. Fixed Size                  1373152 bytes  
  14. Variable Size              92277792 bytes  
  15. Database Buffers           50331648 bytes  
  16. Redo Buffers                6684672 bytes  
  17. Database mounted.  
  18.   
  19. HELLODBA.COM>recover database until cancel;  
  20. Media recovery complete.  
  21. HELLODBA.COM>ALTER DATABASE DATAFILE 'E:\ORA11GR1\ORADATA\ORA11R2\DEMO_DATA.DBF' ONLINE;  
  22.   
  23. Database altered.  
  24.   
  25. HELLODBA.COM>alter database open resetlogs;  
  26.   
  27. Database altered.  

创建一个临时表空间,并修改各个用户的临时表空间。因为我们在用EXP导出时,可能会用到临时表空间

SQL代码
  1. HELLODBA.COM>CREATE TEMPORARY TABLESPACE temp2 TEMPFILE 'E:\ORA11GR1\ORADATA\ORA11R2\TEMP2.DBF' size 1G;  
  2.   
  3. Tablespace created.  
  4.   
  5. HELLODBA.COM>select 'ALTER USER '||username||' TEMPORARY TABLESPACE TEMP2;' from dba_users;  
  6.   
  7. 'ALTERUSER'||USERNAME||'TEMPORARYTABLESPACETEMP2;'  
  8. ---------------------------------------------------------------------  
  9. ALTER USER OUTLN TEMPORARY TABLESPACE TEMP2;  
  10. ... ...  
  11.   
  12. HELLODBA.COM>ALTER USER OUTLN TEMPORARY TABLESPACE TEMP2;  
  13.   
  14. User altered.  
  15.   
  16. ... ...  
  17.   
  18. HELLODBA.COM>exit  

OK。现在可以用EXP将数据导出了

SQL代码
  1. D:\OracleDoc\bbed9i>exp system/oracle tablespaces=DEMO_DATA file=resecue.dat log=resecue.log  
  2. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production  
  3. With the Partitioning, OLAP, Data Mining and Real Application Testing options  
  4. Export done in AL32UTF8 character set and AL16UTF16 NCHAR character set  
  5.   
  6. About to export selected tablespaces ...  
  7. For tablespace DEMO_DATA ...  
  8. . exporting cluster definitions  
  9. . exporting table definitions  
  10. . . exporting table                             AA          1 rows exported  
  11. ... ...  
  12. . . exporting table              TRANSACTIONS_BACK         10 rows exported  
  13. . . exporting table                        TSOURCE       9517 rows exported  
  14. . . exporting table                   TSOURCE_BACK       9517 rows exported  
  15. . . exporting table                          USERS         13 rows exported  
  16. . exporting referential integrity constraints  
  17. EXP-00112: Index T1_IDX_7 is of XMLType and could not be exported  
  18. EXP-00078: Error exporting metadata for index T1_IDX_7. Index creation will be skipped  
  19. EXP-00112: Index T_XML_TAB1_IDX_1 is of XMLType and could not be exported  
  20. EXP-00078: Error exporting metadata for index T_XML_TAB1_IDX_1. Index creation will be skipped  
  21. . exporting triggers  
  22. Export terminated successfully with warnings.  

这个环境中的恢复过程比较顺利。

而在下一个测试当中,我遇到更加复杂的情况:系统表空间保护两个不连续的系统文件;恢复过程中出现ORA错误及数据字典不匹配的情况。我借助了一些非常规的手段规避这些问题,达到数据拯救的目的。这一过程将在下一篇文章中演示。

--- Fuyuncat ---

Top

Copyright ©2005,HelloDBA.Com 保留一切权利

申明
by fuyuncat