[20250515]drop table相关数据段的确定与恢复.txt

[20250515]drop table相关数据段的确定与恢复.txt

--//这几天一直在做truncare table,drop table的非常规恢复,通过修改obj$表的DATAOBJ#指向原来的数据段号,然后通过rowid扫描
--//的方式收集数据。该方式最大的缺点就是恢复很慢,原始的脚本定义行号是999,而且如果扫描数据块范围很大的情况下,真是很慢.
--//我第一次尝试没有修改脚本使用行号999,后面修改150才快了不少。

--//如果通过redo分析,确定扫描范围,这样通过bbed进一步确定每块的最大行号,这样就可以大大加快恢复进度。
--//本文尝试如何通过分析redo的转储,确定drop table的相关数据段的占用数据块的范围。

--//我看了以前的笔记,[20181210]truncate的另外恢复4.txt,通过修改段头,恢复原来的信息,这样难度太大,应该很容易分析redo
--//的转储获得相关信息。

1.环境:
SCOTT@book01p> @ver2
==============================
PORT_STRING                   : x86_64/Linux 2.4.xx
VERSION                       : 21.0.0.0.0
BANNER                        : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL                   : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY                 : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID                        : 0
PL/SQL procedure successfully completed.

ALTER TABLESPACE USERS
  ADD DATAFILE '/u01/oradata/BOOK/book01p/users02.dbf'
  SIZE 100M
  AUTOEXTEND ON
  NEXT 4M
  MAXSIZE UNLIMITED;
--//表空间users增加1个数据文件,比较符合许多生产系统的情况。

2.测试环境建立:

SCOTT@book01p> create table t8 as select * from all_objects;
Table created.
--//分析略。

SCOTT@book01p> select count(*) from t8;
  COUNT(*)
----------
     69896

SCOTT@book01p> create unique index pk_t8 on t8 (object_id);
Index created.

SCOTT@book01p> alter table t8 add constraint pk_t8 primary key (object_id);
Table altered.

SCOTT@book01p> create index i_t8_OBJECT_NAME on t8(OBJECT_NAME);
Index created.
--//建立一些索引比较符合实际的情况。

3.先转储该表的数据段头:
SCOTT@book01p> @ seg2z T8 ''
==============================
SEG_MB                        : 12
SEG_OWNER                     : SCOTT
SEG_SEGMENT_NAME              : T8
SEG_PARTITION_NAME            :
SEG_SEGMENT_TYPE              : TABLE
SEG_TABLESPACE_NAME           : USERS
BLOCKS                        : 1536
HDRFIL                        : 12
HDRBLK                        : 170
PL/SQL procedure successfully completed.

SCOTT@book01p> column PARTITION_NAME noprint
SCOTT@book01p> select * from dba_extents where segment_name='T8' order by EXTENT_ID;
OWNER SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME EXTENT_ID FILE_ID BLOCK_ID    BYTES BLOCKS RELATIVE_FNO
----- ------------ ------------ --------------- --------- ------- -------- -------- ------ ------------
SCOTT T8           TABLE        USERS                   0      12      168    65536      8           12
SCOTT T8           TABLE        USERS                   1      12      176    65536      8           12
SCOTT T8           TABLE        USERS                   2      12      184    65536      8           12
SCOTT T8           TABLE        USERS                   3      12      192    65536      8           12
SCOTT T8           TABLE        USERS                   4      12      200    65536      8           12
SCOTT T8           TABLE        USERS                   5      12      208    65536      8           12
SCOTT T8           TABLE        USERS                   6      12      216    65536      8           12
SCOTT T8           TABLE        USERS                   7      12      224    65536      8           12
SCOTT T8           TABLE        USERS                   8      12      232    65536      8           12
SCOTT T8           TABLE        USERS                   9      12      240    65536      8           12
SCOTT T8           TABLE        USERS                  10      12      248    65536      8           12
SCOTT T8           TABLE        USERS                  11      12    24576    65536      8           12
SCOTT T8           TABLE        USERS                  12      12    24584    65536      8           12
SCOTT T8           TABLE        USERS                  13      12    24592    65536      8           12
SCOTT T8           TABLE        USERS                  14      12    24600    65536      8           12
SCOTT T8           TABLE        USERS                  15      12    24608    65536      8           12
SCOTT T8           TABLE        USERS                  16      18      128  1048576    128           18
SCOTT T8           TABLE        USERS                  17      12      256  1048576    128           12
SCOTT T8           TABLE        USERS                  18      18      256  1048576    128           18
SCOTT T8           TABLE        USERS                  19      12      384  1048576    128           12
SCOTT T8           TABLE        USERS                  20      18      384  1048576    128           18
SCOTT T8           TABLE        USERS                  21      12      512  1048576    128           12
SCOTT T8           TABLE        USERS                  22      18      512  1048576    128           18
SCOTT T8           TABLE        USERS                  23      12      640  1048576    128           12
SCOTT T8           TABLE        USERS                  24      18      640  1048576    128           18
SCOTT T8           TABLE        USERS                  25      12      768  1048576    128           12
SCOTT T8           TABLE        USERS                  26      18      768  1048576    128           18
27 rows selected.
--//EXTENT_ID 0-15使用的数据文件12,EXTENT_ID=16开始使用数据文件18,然后相互交叉使用。
--//实际上Extent Map的信息与查询dba_extents视图结果一致。
--//理论讲扫描范围是 Data dba 到  对应Extent Map看到的dba + length -1.
--//注:表太小,没有看到L2 dba的情况。

4.看看drop table的情况:

$ cat dr.txt
column member new_value v_member
column member noprint
set numw 12
pause run alter system archive log current or alter system switch logfile;
--//12c不允许在pluggable database执行这条命令
--//alter system archive log current;
set termout off
SELECT  member FROM v$log a, v$logfile b WHERE a.group#(+) = b.group# and a.STATUS='CURRENT' and rownum=1;
set termout on

column curr1 new_value v_curr1
select current_scn curr1 from v$database;

--//以下操作内容:
drop table t8 purge;
--//以上操作内容:

column curr2 new_value v_curr2
select current_scn curr2 from v$database;

prompt exec DBMS_LOGMNR.START_LOGMNR(STARTSCN => &&v_curr1 ,ENDSCN  => &&v_curr2 ,OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + DBMS_LOGMNR.CONTINUOUS_MINE);
prompt alter system dump logfile '&&v_member' scn min &&v_curr1 scn max &&v_curr2;
@ti
alter system dump logfile '&&v_member' scn min &&v_curr1 scn max &&v_curr2;

SCOTT@book01p> @ dr.txt
run alter system archive log current or alter system switch logfile
       CURR1
------------
    41722606
Table dropped.
       CURR2
------------
    41722643

exec DBMS_LOGMNR.START_LOGMNR(STARTSCN =>     41722606 ,ENDSCN  =>     41722643 ,OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + DBMS_LOGMNR.CONTINUOUS_MINE)
alter system dump logfile '/u01/oradata/BOOK/redo02.log' scn min     41722606 scn max     41722643
New tracefile_identifier = /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3627_0001.trc
System altered.

5.尝试恢复:
--//分析转储:
$ egrep  "ADD: dba|ADDAXT:" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3627_0001.trc
--//居然不能像truncate那样看到相关信息。

--//仔细查看redo转储,可以发现如下信息:
REDO RECORD - Thread:1 RBA: 0x0000d1.00000103.01a8 LEN: 0x0054 VLD: 0x01 CON_UID: 1073777561
SCN: 0x00000000027ca30c SUBSCN: 98 05/15/2025 08:40:22
CHANGE #1 MEDIA RECOVERY MARKER CON_ID:3 SCN:0x0000000000000000 SEQ:0 OP:18.3 ENC:0 FLG:0x0000
Reuse redo entry
Range reuse: pdb = 3 tsn=5 base=0x030000a8 nblks=8
--//dba 12,170 = file#,block# dba(10): 50331818 = file#,block# dba(16): 0x30000aa,段头
--//0x030000a8 = set dba 12,168 = alter system dump datafile 12 block 168 = 50331816
--//回收使用空间,但是保留1个extent。

$ grep 30000a /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3627_0001.trc
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027c9cb3 SEQ:1 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:1 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:2 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:3 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:4 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:5 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:6 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:7 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:8 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:9 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:10 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:11 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:12 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:13 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:14 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:15 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:16 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:17 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:18 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:19 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:20 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:21 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:22 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:23 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:24 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:25 OP:14.4 ENC:0 RBL:0 FLG:0x0000
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027ca30c SEQ:26 OP:14.2 ENC:0 RBL:0 FLG:0x0000
Range reuse: pdb = 3 tsn=5 base=0x030000a8 nblks=8
--//0x030000a8 = set dba 12,168 = alter system dump datafile 12 block 168 = 50331816

--//节选其中第1个:
REDO RECORD - Thread:1 RBA: 0x0000d1.000000ee.0170 LEN: 0x00a0 VLD: 0x01 CON_UID: 1073777561
SCN: 0x00000000027ca30c SUBSCN:  2 05/15/2025 08:40:22
CHANGE #1 CON_ID:3 TYP:0 CLS:4 AFN:12 DBA:0x030000aa OBJ:129569 SCN:0x00000000027c9cb3 SEQ:1 OP:14.4 ENC:0 RBL:0 FLG:0x0000
kteop redo - redo operation on extent map
   DELETE: entry:26
   shift back: dba:0x0 len:0
   SETSTAT: exts:26 blks:1408 lastmap:0x0 mapcnt:0
CHANGE #2 CON_ID:3 TYP:0 CLS:13 AFN:18 DBA:0x04800002 OBJ:4294967295 SCN:0x00000000027ca309 SEQ:1 OP:22.2 ENC:0 RBL:0 FLG:0x0000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ktfbhredo - File Space Header Redo:
Header Opcode:
Save: Free Extent:
Begin: 768, Length: 128, Instance: 0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--//对比truncate的情况,两者完全不同。

REDO RECORD - Thread:1 RBA: 0x0000d1.000000ef.0020 LEN: 0x0048 VLD: 0x01 CON_UID: 1073777561
SCN: 0x00000000027ca30c SUBSCN:  3 05/15/2025 08:40:22
CHANGE #1 CON_ID:3 TYP:0 CLS:12 AFN:18 DBA:0x04800003 OBJ:4294967295 SCN:0x00000000027ca309 SEQ:1 OP:22.5 ENC:0 RBL:0 FLG:0x0000
ktfbbredo - File BitMap Block Redo:
Free Bits:
Begin: 80, Length: 16
 
REDO RECORD - Thread:1 RBA: 0x0000d1.000000ef.0068 LEN: 0x0040 VLD: 0x01 CON_UID: 1073777561
SCN: 0x00000000027ca30c SUBSCN:  4 05/15/2025 08:40:22
CHANGE #1 CON_ID:3 TYP:0 CLS:13 AFN:18 DBA:0x04800002 OBJ:4294967295 SCN:0x00000000027ca30c SEQ:1 OP:22.2 ENC:0 RBL:0 FLG:0x0000
ktfbhredo - File Space Header Redo:
Header Opcode:
Save: No Pending Op
 
REDO RECORD - Thread:1 RBA: 0x0000d1.000000ef.00a8 LEN: 0x0054 VLD: 0x01 CON_UID: 1073777561
SCN: 0x00000000027ca30c SUBSCN:  5 05/15/2025 08:40:22
CHANGE #1 MEDIA RECOVERY MARKER CON_ID:3 SCN:0x0000000000000000 SEQ:0 OP:18.3 ENC:0 FLG:0x0000
Reuse redo entry
Local range reuse: pdb = 3 tsn=5 base=0x03000300 nblks=2
--//只有输出下划线的信息才知道原来这些extents的相关信息。涉及文件号,开始块号,长度等信息。
 
$ awk '/^CHANGE .*DBA:0x030000aa/,/^ $/{print $0}' /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3627_0001.trc >| zzz1.txt
--//每个段落分割出现1个空行,实际上包含1个空格的空行,在vim下执行:set list可以发现,使用/^ $/作为结束。

$ awk '/^CHANGE #2 /{print substr($6,5)};/^Begin: /{print $2 $4}' zzz1.txt  | paste -d',' - - | awk -F"," '{print $1,$2,$2+$3-1}' | tac > zzz2.txt
$ head -4 zzz2.txt
12 176 183
12 184 191
12 192 199
12 200 207
--//注意追加1行12 168 175

SYS@book01p> @ versions obj$ OBJ#,DATAOBJ#,name,mtime s '' '' "versions_operation='D' and name='T8'"
VERSIONS_STARTTIME   VERSIONS_ENDTIME     VERSIONS_STARTSCN VERSIONS_ENDSCN VERSIONS_XID     V ROWID                    OBJ#   DATAOBJ# NAME MTIME
-------------------- -------------------- ----------------- --------------- ---------------- - ------------------ ---------- ---------- ---- -------------------
2025-05-15 08:40:21.                               41722615                 03001A00DC1F0000 D AAAAASAABAAAI6CAAC     129569     129569 T8   2025-05-15 08:33:16
--//实际上看转储就知道doid号 129569。

$ cat zzz2.txt | xargs -IQ echo ./finddoid.sh Q 129569| bash
scan range file# = 12 begin_block =168 end_block = 175 , doid = 129569 max_row = 66
scan result in 129569_scan.txt , scan max rows num result in 129569_max_rowsnum.txt

scan range file# = 12 begin_block =176 end_block = 183 , doid = 129569 max_row = 63
scan result in 129569_scan.txt , scan max rows num result in 129569_max_rowsnum.txt
...

scan range file# = 18 begin_block =768 end_block = 895 , doid = 129569 max_row = 60
scan result in 129569_scan.txt , scan max rows num result in 129569_max_rowsnum.txt


--//使用t8_bak保存rowid扫描的数据记录。
SCOTT@book01p> create table t8_bak tablespace tsp_audit as select * from all_objects  where 0=1;
Table created.

$ paste -d"," 129569_scan.txt 129569_max_rowsnum.txt | xargs -IQ echo " insert into scanblock values ( Q ); " >| zzz3.txt

SCOTT@book01p> create table scanblock ( file_id number,block_id number,rowsnum number   )  tablespace TSP_AUDIT;
Table created.
--//执行zzz3.txt脚本,不要忘记提交。

SCOTT@book01p> create table t8 SEGMENT CREATION IMMEDIATE as select * from all_objects where 0=1;
Table created.

SCOTT@book01p> @ o2z t8
==============================
O_OWNER                       : SCOTT
O_OBJECT_NAME                 : T8
O_OBJECT_TYPE                 : TABLE
SEG_PART_NAME                 :
O_STATUS                      : VALID
OID                           : 130057
D_OID                         : 130057
CREATED                       : 2025-05-15 10:02:55
LAST_DDL_TIME                 : 2025-05-15 10:02:55
PL/SQL procedure successfully completed.

SCOTT@book01p> @ seg2z t8 ''
==============================
SEG_MB                        : 0
SEG_OWNER                     : SCOTT
SEG_SEGMENT_NAME              : T8
SEG_PARTITION_NAME            :
SEG_SEGMENT_TYPE              : TABLE
SEG_TABLESPACE_NAME           : USERS
BLOCKS                        : 8
HDRFIL                        : 12
HDRBLK                        : 170
PL/SQL procedure successfully completed.
--//理论讲应该建立在另外的数据文件,避免覆盖,测试环境相对可控,问题不大,还是使用原来的段头,数据段没有被破坏。

SYS@book01p> update (select OBJ#,DATAOBJ#,OWNER#,NAME from obj$ where obj#=130057) set DATAOBJ#=129569;
1 row updated.

SYS@book01p> commit ;
Commit complete.

SYS@book01p> alter system flush shared_pool;
System altered.

SYS@book01p> set timing on
SYS@book01p> @ txt/truncTz.txt SCOTT T8 SCOTT T8_BAK ''
PL/SQL procedure successfully completed.
Elapsed: 00:00:04.02
SYS@book01p> set timing off

SCOTT@book01p> select count(*) from t8_bak;
    COUNT(*)
------------
       69896
--//恢复数量完成正确。
posted @ 2025-05-15 21:10  lfree  阅读(16)  评论(0)    收藏  举报