Oracle数据恢复方法
经常有朋友遇到Oracle数据库有数据恢复的需求,这类需求一般分为Oracle中表的数据被误truncate,或者被误delete/drop,或者Oracle数据文件被误删除rm/delete,或者oracle所存放的磁盘/存储/文件系统出现了各类硬件/软件故障。对于不同的恢复场景,如果有Oracle的逻辑备份exp/expdp 或物理备份rman,则优先考虑使用备份恢复数据。但如果没有任何有效的备份,那么我们需要选择不同的恢复方案。
恢复被truncate误删除的Oracle数据
- 01
对于oracle中表被truncate误截断删除的场景,可以基于ORACLE PRM-DUL的truncate恢复功能来将被删除数据恢复出来
- 02
Windows平台下的启动PRM-DUL方法 首先保证JDK已正确安装且java已经加入到环境变量中: 双击PRM-DUL解压目录下的PRM-DUL.bat
- 03
PRM-DUL.bat会在后台启动PRM:
- 04
并启动PRM-DUL 图形化主界面:
- 05
启动PRM-DUL ,并选择 Tools => Recovery Wizard
- 06
点击Next
- 07
在此TRUNCATE场景中并未采用ASM存储,所以仅需要选择 《Dictionary Mode》字典模式即可:
- 08
下一步骤 我们要选择几个参数 : 包括Endian 字节序和DB NAME 由于ORACLE数据文件在不同的操作系统平台上采用了不同的Endian字节序格式,字节序和平台对应列表如下: Solaris[tm] OE (32-bit)Big Solaris[tm] OE (64-bit)Big Microsoft Windows IA (32-bit)Little Linux IA (32-bit)Little AIX-Based Systems (64-bit)Big HP-UX (64-bit)Big HP Tru64 UNIXLittle HP-UX IA (64-bit)Big Linux IA (64-bit)Little HP Open VMSLittle Microsoft Windows IA (64-bit)Little IBM zSeries Based LinuxBig Linux x86 64-bitLittle Apple Mac OSBig Microsoft Windows x86 64-bitLittle Solaris Operating System (x86)Little IBM Power Based LinuxBig HP IA Open VMSLittle Solaris Operating System (x86-64)Little Apple Mac OS (x86-64)Little 例如在传统Unix AIX-Based Systems (64-bit) 、HP-UX (64-bit) 上使用的是Big Endian大端字节序,则这里要选为Big Endian:
- 09
否则例如常见的Linux x86-64 、Windows都保持为默认的Little Endian:
- 10
注意事项: 如果你的数据文件是在AIX(即Big Endian的)上生成的,你为了方便而将这些数据文件拷贝到Windows服务器上并使用PRM-DUL来恢复数据,那么你仍应当选择其原生的Big Endian格式。
- 11
点击Next 点击Choose Files, 一般我们推荐 如果数据库不大,那么将该库所有的数据文件都选择进来; 如果你的数据库很大,且你了解你的数据表位于哪些数据文件上,则你可以仅仅选择SYSTEM表空间的数据文件(必须!)以及数据所在的数据文件。 注意Choose界面支持Ctrl + A 和Shift等键盘操作:
- 12
之后需要为指定的数据文件指定其Block Size即ORACLE数据块的大小,这里根据实际情况修改即可, 例如你的DB_BLOCK_SIZE是8K,但是部分表空间指定16K作为数据块大小的,仅仅需要为那些不是8k的数据文件修改BLOCK_SIZE即可。 这里的OFFSET 参数主要是为了那些采用裸设备存放数据文件的场景,例如在AIX上基于普通VG的LV作为数据文件,则存在4k的OFFSET,需要在此处指定。 如果你恰巧正在使用裸设备数据文件,而又不知道OFFSET到底是多少? 则可以使用$ORACLE_HOME/bin下自带的dbfsize工具查看,如下面的例子高亮部分显示该裸设备具有4K的OFFSET $dbfsize /dev/lv_control_01Database file: /dev/lv_control_01 Database file type: raw device without 4K starting offset Database file size: 334 16384 byte blocks 由于此场景中所有数据文件均为8K的BLOCK SIZE,且基于文件系统所以均没有OFFSET,点击Load
- 13
Load阶段PRM-DUL会从SYSTEM表空间中读取ORACLE数据字典信息,并在自带的Derby中自建一个数据字典,这让PRM-DUL有能力操作ORACLE数据库中的各种数据。
- 14
Load完成后会在后台输出数据库 字符集和国家字符集等信息:
- 15
Load完成后 PRM-DUL界面左侧出现按照数据库用户分组的树形图 点开USERS,可以看到多个用户名,例如用户需要恢复PD SCHEMA下的一张表,则点开PD ,并双击表名:
- 16
由于该TORDERDETAIL_HIS表之前已经被TRUNCATED掉了,所以双击没有显示有数据,此时在表上右键选择Unload truncated data:
- 17
PRM-DUL将尝试扫描该表所在表空间并将已经truncated掉的数据抽取出来:
- 18
如上图所示从已经被TRUNCATE过的TORDERDETAIL_HIS表中抽取出完整的984359条记录,并存放在提示指定的路径下。 这里还自动生成了将文本数据导入到数据库中使用的SQLLDR 控制文件。 $ cd /home/oracle/PRM-DUL/PRM-DULdata/parnassus_dbinfo_PARNASSUSDATA/$ ls -l ParnassusData* -rw-r–r– 1 oracle oinstall 495 Jan 18 08:31 ParnassusData.torderdetail_his.ctl -rw-r–r– 1 oracle oinstall 191164826 Jan 18 08:32 ParnassusData.torderdetail_his.dat.truncated $ cat ParnassusData.torderdetail_his.ctl LOAD DATA INFILE ‘ParnassusData.torderdetail_his.dat.truncated’ APPEND INTO TABLE ParnassusData.torderdetail_his FIELDS TERMINATED BY ‘ ‘ OPTIONALLY ENCLOSED BY ‘”‘ TRAILING NULLCOLS ( “SEQ_ID” , “SI_STATUS” , “D_CREATEDATE” , “D_UPDATEDATE” , “B_ISDELETE” , “N_SHOPID” , “N_ORDERID” , “C_ORDERCODE” , “N_MEMBERID” , “N_SKUID” , “C_PROMOTION” , “N_AMOUNT” , “N_UNITPRICE” , “N_UNITSELLINGPRICE” , “N_QTY” , “N_QTYFREE” , “N_POINTSGET” , “N_OPERATOR” , “C_TIMESTAMP” , “H_SEQID” , “N_RETQTY” , “N_QTYPOS” ) 将数据导入到源表中(注意 ParnassusData强烈建议你修改该SQLLDR控制文件中导入的表名字为一个临时表,这样不会覆盖原环境)。 $ sqlldr control=ParnassusData.torderdetail_his.ctl direct=yUsername:/ as sysdba//以上使用sqlldr导入了恢复的数据 //可以通过minus来对比恢复出来的数据: select * from ParnassusData.torderdetail_his minus select * from parnassus.torderdetail_his; no rows selected 测试TRUNCATE用例表与源数据表对比,发现记录完全一致。 说明PRM-DUL完整、丝毫不差地恢复了被TRUNCATE表上的记录。
恢复被delete误删除的Oracle数据
- 01
对于没有有效物理或逻辑备份的场景,当Oracle中发生delete误操作时 一般会优先考虑使用flashback闪回或logminer日志挖掘等技术来恢复Oracle表中的数据行记录,但很多时候flashback或logminer都无法力挽狂澜。 对于delete操作而言,其对于oracle底层数据块block中的row piece记录一般仅仅是修改其row flag标记为已删除标记,容许后续INSERT的记录覆盖这些被标记为delete的数据,也容许破坏这些delete掉的数据的结构。 换句话说如果delete后没有对表做什么操作的话,直接读取block中的这些被标记为deleted的记录还是有可能读取到完整数据的。 总而言之,是否能恢复这部分delete掉的数据,完全取决于磁盘上oracle block中这部分删除的数据行是否有被最终清理掉。 在被清理掉之前ORACLE PRM-DUL工具都可以尝试把这部分数据恢复出来, 具体步骤与普通的数据字典模式差别很小。 启动PRM-DUL 点击恢复向导 字典模式
- 02
加入所有oracle数据文件,不需要加入临时文件TEMPFILE、UNDO数据文件、控制文件、日志文件
- 03
点击load 按钮,PRM会自动加载数据字典 即bootstrap动作
- 04
至此 PRM左侧将出现 树形的对象树,选择你需要恢复的用户下的对应数据表, 右击对象后选择 unload deleted data
恢复被误drop的Oracle表Table
- 01
对于误操作DROP TABLE的数据恢复 D公司的应用开发人员在ASM存储环境下,在没有任何备份的情况下DROP了系统中一张核心应用表,此时第一时间采用PRM-DUL可以恢复该DROP掉数据表的绝大部分数据。10g以后提供了 recyclebin回收站特性,可以首先通过查询DBA_RECYCLEBINS视图来确定被DROP掉的表是否在回收站中,如果在则优先通过回收站flashback to before drop,如果回收站中也没有了,则第一时间使用PRM-DUL恢复。
- 02
恢复简要流程如下: 首先将被DROP掉的数据表所在的表空间OFFLINE 通过查询数据字典或者LOGMINER找到被DROP掉数据表的DATA_OBJECT_ID,如果此步骤中得不到这个DATA_OBJECT_ID,则需要在NON-DICT非字典模式下 启动PRM-DUL,进入NON-DICT非字典模式,并加入被DROP掉数据表所在的表空间的所有数据文件,之后SCAN DATABASE+SCAN TABLE from Extent MAP 通过DATA_OBJECT_ID定位到展开对象树形图中对应的数据表,采用DataBridge模式插回到源数据库中
- 03
首先将被DROP掉的数据表所在的表空间OFFLINE SQL> select tablespace_name from dba_segments where segment_name=’TPAYMENT’;TABLESPACE_NAME —————————— USERS SQL> select file_name from dba_data_files where tablespace_name=’USERS’; FILE_NAME —————————————————————- +DATA1/parnassus/datafile/users.263.843694795 SQL> alter tablespace users offline; Tablespace altered. 启动PRM-DUL到NON-DICT模式,并加入对应的数据文件选择SCAN DATABASE+SCAN TABLE From Extents:
- 04
由于是在非字典模式下所有需要输入必要的字符集信息:
- 05
选择被DROP掉的表所在的数据文件即可,多余的数据文件可不选择,并点击SCAN:
- 06
点中生成的数据库名,并右键选择scan tables from extents:
- 07
通过人工识别发现DATA_OBJECT_ID=82641的数据对应于被DROP掉的TORDERDETAIL_HIS表,通过DataBridge技术将其传输回源库别的表空间中。
对于误操作DROP TABLESPACE的Oracle数据恢复
- 01
D公司的员工需要删除某个无用的表空间即DROP TABLESPACE INCLUDING CONTENTS操作,但是在操作DROP TABLESPACE后,开发部门反映该被DROP掉的TABLESPACE上其实有一个SCHEMA的数据是有用且重要的,但现在表空间被DROP了,且无任何备份。
- 02
此时可以利用PRM-DUL的No-Dict模式去抽取被DROP TABLESPACE的对应的所有数据文件中的数据。 通过这种方式可以恢复大部分数据,但由于是非字典模式所以需要将恢复出来的表与应用数据表一一对应起来,此时一般需要应用开发维护人员介入,通过人工识别来分辨哪些数据属于哪张表。由于DROP TABLESPACE操作修改了数据字典,并在OBJ$中删除了对应表空间上的对象,所以无法从OBJ$上获得DATA_OBJECT_ID与OBJECT_NAME之间的对应关系。此时我们可以利用如下的方法,尽可能多得获取DATA_OBJECT_ID与OBJECT_NAME之间的对应关系。
- 03
此时通过文件恢复工具例如Windows平台上可以使用UNDELETER将被误删除的数据文件还原出来
- 04
启动PRM-DUL => recovery Wizard => 非字典模式
- 05
由于是非字典模式,所以需要自己选择合理的字符集!
- 06
加入刚才恢复出来的数据文件并点击扫描
- 07
之后选择从段头/盘区扫描表,如果从段头扫描表未能找到所有表,则考虑用从盘区扫描:
- 08
此时可以看到主界面树形图出现大量OBJXXXXX的表,这里的OBJXXXXX实际就是表的DATA_OBJECT_ID,一般如果有熟悉该套系统应用模式开发的技术人员可以通过浏览样本数据分析将该表与应用表对应起来:
- 09
如果没有人可以帮忙对应数据与表之间的关系,则可以考虑使用如下的手段: 由于此例子中仅仅是DROP了TABLESPACE表空间,而数据库本身完全是可用的,则此时可以利用FLASHBACK QUERY来获得DATA_OBJECT_ID与表名之间的映射关系。 SQL> select count(*) from sys.obj$;COUNT(*) ———- 75436 SQL> select count(*) from sys.obj$ as of scn 1895940; select count(*) from sys.obj$ as of scn 1895940 * 第 1 行出现错误: ORA-01555: 快照过旧: 回退段号 0 (名称为 “SYSTEM”) 过小 一开始想利用FLASHBACK QUERY来找出OBJ$上之前的记录,但是发现由于使用SYSTEM ROLLBACK SEGMENT所以会出现ORA-01555错误 此时可以考虑使用AWR视图DBA_HIST_SQL_PLAN,只要在最近7天中访问过该表一般可以从执行计划中获得OBJECT#和OBJECT_NAME的映射关系: SQL> desc DBA_HIST_SQL_PLAN 名称 是否为空? 类型 —————————————– ——– ———————– DBID NOT NULL NUMBER SQL_ID NOT NULL VARCHAR2(13) PLAN_HASH_VALUE NOT NULL NUMBER ID NOT NULL NUMBER OPERATION VARCHAR2(30) OPTIONS VARCHAR2(30) OBJECT_NODE VARCHAR2(128) OBJECT# NUMBER OBJECT_OWNER VARCHAR2(30) OBJECT_NAME VARCHAR2(31) OBJECT_ALIAS VARCHAR2(65) OBJECT_TYPE VARCHAR2(20) OPTIMIZER VARCHAR2(20) PARENT_ID NUMBER DEPTH NUMBER POSITION NUMBER SEARCH_COLUMNS NUMBER COST NUMBER CARDINALITY NUMBER BYTES NUMBER OTHER_TAG VARCHAR2(35) PARTITION_START VARCHAR2(64) PARTITION_STOP VARCHAR2(64) PARTITION_ID NUMBER OTHER VARCHAR2(4000) DISTRIBUTION VARCHAR2(20) CPU_COST NUMBER IO_COST NUMBER TEMP_SPACE NUMBER ACCESS_PREDICATES VARCHAR2(4000) FILTER_PREDICATES VARCHAR2(4000) PROJECTION VARCHAR2(4000) TIME NUMBER QBLOCK_NAME VARCHAR2(31) REMARKS VARCHAR2(4000) TIMESTAMP DATE OTHER_XML CLOB 例如: select object_owner,object_name,object# from DBA_HIST_SQL_PLAN where sql_id=’avwjc02vb10j4′ OBJECT_OWNER OBJECT_NAME OBJECT# ——————– —————————————- ———- PARNASSUSDATA TORDERDETAIL_HIS 78688 可以利用如下脚本获得较多OBJECT_ID与OBJECT_NAME的映射关系 Select * from (select object_name,object# from DBA_HIST_SQL_PLAN UNION select object_name,object# from GV$SQL_PLAN) V1 where V1.OBJECT# IS NOT NULL minus select name,obj# from sys.obj$; select obj#,dataobj#, object_name from WRH$_SEG_STAT_OBJ where object_name not in (select name from sys.obJ$) order by object_name desc; 另一个查询: SELECT tab1.SQL_ID, current_obj#, tab2.sql_text FROM DBA_HIST_ACTIVE_SESS_HISTORY tab1, dba_hist_sqltext tab2 WHERE tab1.current_obj# NOT IN (SELECT obj# FROM sys.obj$ ) AND current_obj#!=-1 AND tab1.sql_id =tab2.sql_id(+); 注意以上方法仅仅在用户确实找不到所要恢复的数据表的任何定义信息时使用(即用户找任何对该应用模式设计有了解的人、脚本和文档),且由于依赖于AWR数据,所以并不十分准确。
针对Oracle数据库打不开无法open的数据恢复
- 01
D 公司的DBA由于误操作删除了TS$数据字典基表导致数据库无法启动 Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 – 64bit ProductionWith the Partitioning, Automatic Storage Management, OLAP, Data Miningand Real Application Testing options INSTANCE_NAME —————- ASMME SQL> SQL> SQL> select count(*) from sys.ts$; COUNT(*) ———- 5 SQL> delete ts$; 5 rows deleted. SQL> commit; Commit complete. SQL> shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. Database mounted. ORA-01092: ORACLE instance terminated. Disconnection forced ORA-01405: fetched column value is NULL Process ID: 5270 Session ID: 10 Serial number: 3 Undo initialization errored: err:1405 serial:0 start:3126020954 end:3126020954 diff:0 (0 seconds) Errors in file /s01/diag/rdbms/asmme/ASMME/trace/ASMME_ora_5270.trc: ORA-01405: fetched column value is NULL Errors in file /s01/diag/rdbms/asmme/ASMME/trace/ASMME_ora_5270.trc: ORA-01405: fetched column value is NULL Error 1405 happened during db open, shutting down database USER (ospid: 5270): terminating the instance due to error 1405 Instance terminated by USER, pid = 5270 ORA-1092 signalled during: ALTER DATABASE OPEN… opiodr aborting process unknown ospid (5270) as a result of ORA-1092
- 02
此场景中由于数据字典已经损坏,所以想要正常打开数据库是十分困难的。 此时则可以使用PRM-DUL来抽取数据库中的数据。具体步骤与场景1中的相似,用户仅仅需要输入该数据库的所有数据文件即可,其简要步骤如下: Recovery Wizard 选择字典模式 Dictionary Mode 合理选择Big或者Little Endian 加入数据文件并点击Load 根据实际需求恢复表中的数据
误删除或丢失了system表空间数据文件的恢复
- 01
D公司的SA系统管理员误删除了某数据库的SYSTEM表空间所在数据文件,这导致数据库完全无法打开,数据无法取出。 在没有备份的情况下,可以使用PRM-DUL恢复接近100%的数据。 此场景中启动PRM-DUL后,进入Recovery Wizard后 选择《Non-Dictionary mode》非字典模式:
- 02
No-dictionary模式下需要用户指定 字符集和国家字符集,这是因为丢失了SYSTEM表空间后,数据库的字符集信息无法正常获得,所以需要用户的输入。 只有输入正确的字符集设置以及安装了必要的语言包才能保证No-Dictionary模式下正常抽取多国语言。 与场景演示1类似,输入用户目前可得的所有数据文件(不包括临时文件),并设置正确的Block Size和OFFSET:
- 03
之后点击SCAN,SCAN的作用是扫描所有数据文件上的Segment Header,并记录到SEG$.DAT和EXT$.DAT中;在ORACLE中一个非分区表或者一个分区表的分区都对应着一个SEGMENT HEADER数据段头,只要能找到SEGMENT HEADER就可以获得整个表数据段的盘区EXTENT MAP 信息,通过EXTENT MAP可以获得该表上的全部记录。
- 04
完成SCAN 后,主界面左侧出现数据库图标。 此时可以选择2种模式: Scan Tables From Segments,此模式适用于 丢失了SYSTEM表空间,但是所有的应用数据表空间均存在 Scan Tables From Extents 不适用于Dictionary模式的Truncate表数据恢复 丢失了SYSTEM表空间,而且丢失了SEGMENT HEADER所在数据文件 通俗地说 除非你无法使用场景2中的方式来恢复已经TRUNCATE掉的数据,否则总是优先使用Scan Tables From Segments模式,如果发现Scan Tables From Segments下找不到你要的数据,再考虑使用Scan Tables From Extents模式。 我们优先采用Scan Tables From Segments模式
- 05
Scan Tables From Segments完成后可以点开主界面左边的树形图:
- 06
Scan Tables操作基于SEG$中的SEGMENT HEADER信息来构建数据表信息,树形图上每一个节点表示一个数据表段,其名字为obj+ 数据段上记录的DATA OBJECT ID 。 点中一个节点 并观察主界面右侧边栏:
误删除了SYSTEM表空间和部分应用表空间数据文件
- 01
D公司的SA由于误操作将在线业务数据库的SYSTEM表空间上的数据文件,以及部分应用表空间数据文件意外删除了。 此场景中由于部分应用表空间数据文件被删除了,这其中可能包括含有数据表的SEGMENT HEADER的数据文件,所以使用Scan Tables From Segment Header可能不如使用Scan Tables From Extents来的合适。 其简要步骤如下: 进入Recovery Wizard ,选择No-Dictionary模,加入所有可用的数据文件,执行Scan Database 选中数据库,并右键Scan Tables From Extents 对于PRM-DUL主界面上生成的对象树形图中的数据进行分析和导出/数据搭桥 其余操作与恢复场景4中一样