震惊,一单几十个W的Oracle非常规恢复,原来这么简单?
前言:
震惊,我也不知道为什么要震惊,现在写公众号好像不“震惊”不太行了,Oracle非常规恢复极其复杂,需要非常扎实的功底,精通底层块结构、数据库原理等,我也是初学者,曾经用bbed工具修复过几次故障,很多细节仍然不是完全明白,但是如果使用恢复工具操作会简单很多,常见的有DUL、ODU等,今天简单介绍下如何使用ODU工具恢复误删除的数据,分为三种误操作类型,分别是TRUNCATE、DELETE、DROP。
说明:
文章整理自2017-12-29我在ITPUB博客发布的以下文章:
Oracle Delete表恢复(ODU)
https://blog.itpub.net/29785807/viewspace-2149488/
Oracle Truncate表恢复 (ODU)
https://blog.itpub.net/29785807/viewspace-2149477/
Oracle Drop表(purge)恢复(ODU)
https://blog.itpub.net/29785807/viewspace-2149476/
测试库版本:11.2.0.1.0
ODU工具版本:3.0.9
注意:文章发布时间较久,可能存在错误,仅供参考,请勿用于生产环境。
下面让我们一起看下这三种误操作如何恢复吧。
#################################
一:表中数据被误TRUNCATE
生成测试数据
create table tt1 as select * from dba_objects;create table tt2 as select * from tt1;select * from dba_objects where object_name='TT1'; ---OBJECT_ID 87295 ---DATA_OBJECT_ID 87295---object_id: Dictionary object number of the object.---Data_object_id: Dictionary object number of the segment that contains the object.
模拟误删除
truncate table tt1;select *from tt1;
使用ODU进行恢复
步骤如下:
(1) OFFLINE表所在的表空间(2) 生成数据字典:unload dict(3) 扫描数据:scan extent(4) 恢复表:unload table username.tablename object auto
1:OFFLINE表所在的表空间
select * from dba_objects where object_name='TT1'; ---OBJECT_ID 87290 ---DATA_OBJECT_ID 87297select tablespace_name from user_tables where table_name='T1'; ---USERSalter tablespace USERS offline;alter system checkpoint;
2:ODU 版本 3.0.9

3:生成数据字典

4:扫描数据

5:恢复表

自动生成以下三个文件

6:通过 sqlldr 加载数据到数据库


7:验证数据
select count(*) from tt1; ---86155select * from tt1;

......
#################################
二:表中数据被误DELETE
创建测试数据
create table t0 as select * from dba_objects;create table t0_bak as select * from t0;select count(*) from t0; ---86159
模拟误删除
delete t0 where object_id>85000; commit;select count(*) from t0; ---84141
如果无有效备份,也无法闪回,如何恢复
使用ODU工具进行恢复
1.:将参数 unload_deleted 设置为 YES
2.:生成数据字典

3:恢复表


rename t0 to tt0;CREATE TABLE "CHEN"."T0"("OWNER" VARCHAR2(30) ,"OBJECT_NAME" VARCHAR2(128) ,"SUBOBJECT_NAME" VARCHAR2(30) ,"OBJECT_ID" NUMBER ,"DATA_OBJECT_ID" NUMBER ,"OBJECT_TYPE" VARCHAR2(19) ,"CREATED" DATE ,"LAST_DDL_TIME" DATE ,"TIMESTAMP" VARCHAR2(19) ,"STATUS" VARCHAR2(7) ,"TEMPORARY" VARCHAR2(1) ,"GENERATED" VARCHAR2(1) ,"SECONDARY" VARCHAR2(1) ,"NAMESPACE" NUMBER ,"EDITION_NAME" VARCHAR2(30));
4:通过 sqlldr 将数据加载到数据库


5 :验证数据
select count(*) from t0; ---86159select * from t0 where object_id>85000;

......
#################################
三:表中数据被误DROP
通过 ODU 恢复 drop 掉的表 (purge) 基本步骤如下
1:offline表所在表空间;2:通过 logminer 挖出被 drop 表对应 object_id ;3:使用 ODU 工具将表数据抽到文件中;4:使用 sqlldr 将数据加载到数据库;5:验证;
准备测试数据
1 创建测试表 odu_test
create table odu_test (a number,b varchar2(10),c nvarchar2(30),d varchar2(20),e date,f timestamp,g binary_float,h binary_double);
2 插入测试数据
insert into odu_testselect rownum,lpad('x', 10),'NC测试 ' || rownum,'ZHS测试 ' || rownum,sysdate + dbms_random.value(0, 100),systimestamp + dbms_random.value(0, 100),rownum + dbms_random.value(0, 10000),rownum + dbms_random.value(0, 10000)from dba_objectswhere rownum exec sys.dbms_logmnr.start_logmnr(options=>sys.dbms_logmnr.dict_from_online_catalog);SQL> select scn,timestamp,sql_redo from v$logmnr_contents where operation='DDL' and sql_redo like '%odu_test%' order by 2 ;......990001 2017/12/27 drop table odu_test purge;SQL> select scn,timestamp,sql_redo from v$logmnr_contents where timestamp=to_date('2017-12-27','yyyy-mm-dd') order by 1;SQL> create table logmnr_1 as (select * from v$logmnr_contents;SQL> exec sys.dbms_logmnr.end_logmnr;select *from sys.logmnr_1 where scn='990001'; ---DATA_OB# 87270select * from sys.logmnr_1 where *operation='DDL' and*/ LOWER(sql_redo) like '%odu_test%' order by 2 ;/*delete from "SYS"."OBJ$" where "OBJ#" = '87270' and "DATAOBJ#" = '87270' and "OWNER#" = '84' and "NAME" = 'ODU_TEST' and "NAMESPACE" = '1' and "SUBNAME" IS NULL and "TYPE#" = '2' and "CTIME" = TO_DATE('27-12 月 -17', 'DD-MON-RR') and "MTIME" = TO_DATE('27-12 月 -17', 'DD-MON-RR') and "STIME" = TO_DATE('27-12 月 -17', 'DD-MON-RR') and "STATUS" = '1' and "REMOTEOWNER" IS NULL and "LINKNAME" IS NULL and "FLAGS" = '0' and "OID$" IS NULL and "SPARE1" = '6' and "SPARE2" = '1' and "SPARE3" = '84' and "SPARE4" IS NULL and "SPARE5" IS NULL and "SPARE6" IS NULL and ROWID = 'AAAAASAABAAAVKkABB';*/
(3)修改原 control.txt 文件
select d.TS# ts,d.FILE# fno,d.FILE# fno,d.NAME filename,d.BLOCK_SIZE block_sizefrom v$datafile dorder by ts;0 1 1 D:APPADMINISTRATORORADATACJCSYSTEM01.DBF 81921 2 2 D:APPADMINISTRATORORADATACJCSYSAUX01.DBF 81922 3 3 D:APPADMINISTRATORORADATACJCUNDOTBS01.DBF 81924 4 4 D:APPADMINISTRATORORADATACJCUSERS01.DBF 8192---control.txt

(4) 登录odu


(5)扫描数据

---企业版 ODU 需要授权

---本次实验使用测试版 ODU
(6) 恢复表



生成创建表的语句和控制文件

这个命令生成了如下文件
ODU_0000087270.ctl 和 ODU_0000087270.sqlCREATE TABLE "ODU_0000087270"("C0001" NUMBER ,"C0002" VARCHAR2(4000) ,"C0003" NVARCHAR2(2000) ,"C0004" VARCHAR2(4000) ,"C0005" DATE ,"C0006" DATE ,"C0007" BINARY_FLOAT ,"C0008" BINARY_DOUBLE);
(7) online 表空间
alter tablespace users online;
(8) 通过 sqlldr 加载数据

(9) 验证数据
select count(*) from ODU_0000087270; ---10000
查看恢复后表数据
select * from ODU_0000087270;

......
###chenjuchao 20240410###
欢迎关注我的公众号《IT小Chen》,后面计划学习并更新一些bbed工具的使用场景,尝试使用bbed恢复数据。