使用odu恢复truncate,drop purge的表
ODU下载:http://www.oracleodu.com
ODU使用手册:http://www.oracleodu.com/soft/ODUUserGuide_cn.pdf
参考:https://www.modb.pro/db/21669
ODU测试
= 创建测试表:cog.test
drop table cog.test purge;
create table cog.test tablespace system as select * from dba_objects where rownum<=100000;
commit;
alter system checkpoint;
select count(1) from cog.test;
select object_id,data_object_id from dba_objects where owner='COG' and object_name='TEST';
OBJECT_ID DATA_OBJECT_ID
---------- --------------
91884 91902
= truncate表 DATA_OBJECT_ID 发生改变
= 情况1:truncate
= 情况2:drop purge
= 情况3:truncate 之后 drop purege
= 情况4:truncate 之后 insert new
= 情况5:drop purge 之后 create new
= 情况4:truncate 之后 drop purge 之后 create new
truncate table cog.test; = truncate
drop table cog.test purge; = purge
insert into cog.test select * from dba_objects where rownum<=10000; = insert
commit;
alter system checkpoint;
select object_id,data_object_id from dba_objects where owner='COG' and object_name='TEST';
OBJECT_ID DATA_OBJECT_ID
---------- --------------
91884 91885
= 编辑control.txt
= select file_name,TABLESPACE_NAME from dba_data_files;
= select * from select * from v$tablespace;
[oracle@qnzw odu]$ cat control.txt
ts fno rfno filename block_size is_big_file header_offset blocks
0 0 0 /u01/qnzw/oradata/pdb1/system_pdb1_01.dbf
= 编辑config.txt
lob_path /u01/odu/data/lob
output_format dmp
charset_name AL32UTF8
compatible 12
= 获取license
./odu
save control
将生成的文件oductl.txt发给http://www.oracleodu.com/cn/support中指定的技术支持邮箱,
然后获得一个名为oductl.dat的LICENSE文件,然后将此文件复制到ODU所在目录。
= 使用odu
rm *.odu data/* oductl.txt odu_trace.txt segment.txt -f = 清理odu测试数据
./odu
unload dict = unload字典信息(完成后会生成很多ODU文件 从system表空间)
scan extent = unload字典信息(成后会生成ext.odu文件,后面的unload抽取操作将依赖于该文件。)
desc cog.test = 如果找不对对象,需要使用logminer来查找被drop表的data object_id:
unload table cog.test
unload table cog.test object truncate
unload table cog.test object 91909
= 抽取数据
odu抽取数据unload命令有3种方式:
desc cog.test
Object ID:91884
Storage(Obj==91884 DataObj==91885 TS==0 File==1 Block==32784 Cluster=0)
1.unload table cog.test
= 用于最后一次恢复drop table purge
= 这种方式的原理是读取tab.odu信息找到段头块,根据段头的extent map抽取数据,很明显这种方式不能用于恢复truncate。
2.unload table cog.test object truncate
= 这种方式的原理是从段头块后面的第一个块依次读取第一个extent,找到第一个dataobj=小于段头dataobj=,
= 然后根据扫描出来的ext.odu来进行抽取。该方式适用于恢复最后一次truncate前的数据,
= 且第一个extent不被覆盖或没有完全覆盖的情况。
3.unload table cog.test object dataobj=
= 这种方式的原理是直接指定dataobj=来进行抽取,抽取依据是扫描出来的ext.odu,
= 具体应该使用哪个dataobj=,之前几篇文章有介绍可以通过logminer或者redodump来获取。
== DMP 导入数据
drop table cog.test purge;
select count(1) from cog.test;
imp cog/cog@pdb1 file=/u01/odu/data/COG_TEST.dmp FULL=Y
imp cog/cog@pdb1 file=/u01/odu/data/ODU_0000091884.dmp FULL=Y
drop table cog.ODU_0000091884 purge;
select count(1) from ODU_0000091884;
== SQLLD 导入数据
sqlldr test/test control=ODU_ODU_0000052230.ctl
====================================================
=== 使用logminer来查找被drop表的data object_id: ===
set line 150 pages 90
col member for a50
col timestamp format a11
col sql_redo format a100
alter session set nls_date_format='dd hh24:mi:ss';
select * from v$log;
select member from v$logfile where group#=2;
exec sys.dbms_logmnr.add_logfile(logfilename=>'/u01/qnzw/oradata/redo02.dbf');
exec sys.dbms_logmnr.start_logmnr(options=>sys.dbms_logmnr.dict_from_online_catalog);
select scn,timestamp,sql_redo from v$logmnr_contents where operation='DDL' and sql_redo like '%test%' order by 2;
select scn,timestamp,sql_redo from v$logmnr_contents where timestamp=to_date('2020-06-10 17:09:33','yyyy-mm-dd hh24:mi:ss') order by 1;
exec sys.dbms_logmnr.end_logmnr;
找到被删除的object_id
where "OBJ#" = '91898' and "DATAOBJ#" = '91899'
这里假设不知道这个表有多少列,每个列的数据类型,我们可以通过 ODU 的抽样来自动判断数据的类型:
./odu
scan extent tablespace 0;
unload object 91898 sample # 抽样判断 判断数据类型
unload object 91898 tablespace 0 column VARCHAR2 VARCHAR2 VARCHAR2 NUMBER NUMBER VARCHAR2 DATE DATE VARCHAR2 VARCHAR2 VARCHAR2 VARCHAR2 VARCHAR2 NUMBER RAW VARCHAR2 VARCHAR2 VARCHAR2
=====================================
=== unload 命令 ====
unload dict [block <bootstrap block=>]
unload table <schema.tablename> [object truncate] [partition <partition_name>]
unload table <schema.tablename> [object scanned] [partition <partition_name>]
unload table <schema.tablename> object <data_obj_id> [tablespace <ts_no>]
unload table <schema.tablename> datafile <rfile=> block <block=> [blocks <blocks>] [partition
<partition_name>]
unload object <data_obj_id> [tablespace <ts_no>] [cluster <cluster_no>] column <type [ type
[ type......]>
type: VARCHAR2 VARCHAR CHAR NUMBER SKIP LONG RAW
DATE LONG_RAW TIMESTAMP TIMESTAMP_TZ TIMESTAMP_LTZ
BINARY_FLOAT BINARY_DOUBLE NVARCHAR2 NCHAR
CLOB NCLOB BLOB
unload object <data_obj_id> [tablespace <ts_no>] [cluster <cluster_no>] sample
unload object all [tablespace <ts_no>] sample
unload user <schema name>
== unload dict
= 从 SYSTEM 表空间解析数据字典,于从 SYSTEM 表空间解析数据字典保存到.odu文件
= 可以使用 list user, list table 等命令查看数据库中的用户及用户下的表、视图等对象。
list user
list table cog
desc cog.test
== unload table <schema.tablename> datafile <rfile=> block <block=>
= [blocks
= 令用于恢复一张表下指定位置的指定数量的块。主要用于当部分块异常时只恢复这部分数据块的数据。
unload table sys.t1 datafile 4 block 651 blocks 10
= unload object <data_obj_id> [tablespace <ts_no>] [cluster<cluster_no>] column <type [ type [ type…]>
= 这条命令简单点说,就是用于没有 SYSTEM 表空间或者没有数据字典时的数据恢复,或用于恢复被 DROP 了的表。
= 列类型为(SKIP 表示不恢复那个列)
VARCHAR2 VARCHAR CHAR NUMBER SKIP LONG RAW
DATE LONGRAW TIMESTAMP TIMESTAMPTZ TIMESTAMPLTZ
BINARY_FLOAT BINARY_DOUBLE NVARCHAR2 NCHAR
CLOB NCLOB BLOB
= 在使用了传输表空间时,不同段对象的 data object id 可能相同,在这种情
= 况下需要指定要恢复的数据所在的表空间号(注意这里是表空间号而不是表空间名)。同一
= 表空间下不同的数据段不可能存在相同的 data object id。
= 指定的列顺序以数据存储在数据块上的顺序为准
= Cluster 表,Cluster列总是存储在最前面
= 有 LONG 或 LONG RAW 类型的列,这两种类型的列总是存储在最后一列。
create table t4 (a number, b long,c varchar2(100));
unload object 42168 column number varchar2 long




