最近在写oracle抽取数据文件工具,在抽取数据文件恢复数据的时候发现,恢复的数据比预期的多,经过对比之后发现是有一些表被truncate了,由于被truncate之后部分块还没有被覆盖。所以这样的数据也就抽取出来了。其实抽取工具的原理就是根据段头、三级块位图、二级块位图、一级块位图等,再加上系统表空间对应的数据文件。最后整合之后就可以转换成表数据。
1、创建测试数据
SQL> create tablespace py datafile ‘/u01/app/oradata/QXY/py.dbf‘ size 5M autoextend off;
Tablespace created.
SQL> create table pygc(id int) tablespace py;
Table created.
SQL> insert into pygc values (10);
1 row created.
SQL> insert into pygc values (11);
1 row created.
SQL> commit;
Commit complete.
SQL> select object_id, data_object_id, object_name from dba_objects where object_name=‘PYGC‘;
OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
136026 136026 PYGC
SQL>
创建一个表空间PY,并在该表空间创建一张表PYGC插入两行数据。表PYGC的对象号为136026。
2、dump表PYGC数据块的信息
SQL> select distinct dbms_rowid.ROWID_RELATIVE_FNO(rowid), dbms_rowid.ROWID_BLOCK_NUMBER(rowid) from PYGC;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
15 134
SQL>
SQL>
SQL> alter system dump datafile 15 block 134;
System altered.
SQL>
SQL> select value from v$diag_info where name = ‘Default Trace File‘;
VALUE
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_4123.trc
SQL>
Block dump from disk:
buffer tsn: 17 rdba: 0x03c00086 (15/134)
scn: 0x0000.0225a6ce seq: 0x01 flg: 0x06 tail: 0xa6ce0601
frmt: 0x02 chkval: 0x8361 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00007F43CF4AF000 to 0x00007F43CF4B1000
7F43CF4AF000 0000A206 03C00086 0225A6CE 06010000 [..........%.....]
7F43CF4AF010 00008361 00000001 0002135A 0225A6CB [a.......Z.....%.]
7F43CF4AF020 00000000 0032F802 03C00080 00010017 [......2.........]
7F43CF4AF030 00002CD0 04C023C2 00060593 00002002 [.,...#....... ..]
7F43CF4AF040 0225A6CE 00000000 00000000 00000000 [..%.............]
7F43CF4AF050 00000000 00000000 00000000 00000000 [................]
7F43CF4AF060 00000000 00020100 0016FFFF 1F701F8C [..............p.]
7F43CF4AF070 00001F70 1F920002 00001F8C 00000000 [p...............]
7F43CF4AF080 00000000 00000000 00000000 00000000 [................]
Repeat 502 times
7F43CF4B0FF0 0201012C 012C0CC1 0BC10201 A6CE0601 [,.....,.........]
Block header dump: 0x03c00086
Object id on Block? Y
seg/obj: 0x2135a csc: 0x00.225a6cb itc: 2 flg: E typ: 1 - DATA
brn: 0 bdba: 0x3c00080 ver: 0x01 opc: 0
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0017.001.00002cd0 0x04c023c2.0593.06 --U- 2 fsc 0x0000.0225a6ce
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
bdba: 0x03c00086
data_block_dump,data header at 0x7f43cf4af064
tsiz: 0x1f98
hsiz: 0x16
pbl: 0x7f43cf4af064
76543210
flag=--------
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x1f8c
avsp=0x1f70
tosp=0x1f70
0xe:pti[0] nrow=2 offs=0
0x12:pri[0] offs=0x1f92
0x14:pri[1] offs=0x1f8c
block_row_dump:
tab 0, row 0, @0x1f92
tl: 6 fb: --H-FL-- lb: 0x1 cc: 1
col 0: [ 2] c1 0b
tab 0, row 1, @0x1f8c
tl: 6 fb: --H-FL-- lb: 0x1 cc: 1
col 0: [ 2] c1 0c
end_of_block_dump
End dump data blocks tsn: 17 file#: 15 minblk 134 maxblk 134
可以看到15号文件的134块包含了2行数据c10b、c10c。该格式是raw格式,转换成number就是10、11。可以通过oracle有自带转换工具dbms_stats.convert_raw_value,我这里进行了封装,转换之后如下:
SQL> select displayraw(‘c10b‘,‘NUMBER‘) from dual;
DISPLAYRAW(‘C10B‘,‘NUMBER‘)
10
SQL> select displayraw(‘c10c‘,‘NUMBER‘) from dual;
DISPLAYRAW(‘C10C‘,‘NUMBER‘)
11
SQL>
3、查看表PYGC段头信息
SQL> col segment_name for a20
SQL> select SEGMENT_NAME,HEADER_FILE,HEADER_BLOCK from dba_segments where segment_name = ‘PYGC‘;
SEGMENT_NAME HEADER_FILE HEADER_BLOCK
PYGC 15 130
SQL>
SQL> alter system dump datafile 15 block 130;
System altered.
SQL> select value from v$diag_info where name = ‘Default Trace File‘;
VALUE
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_4893.trc
SQL>
buffer tsn: 17 rdba: 0x03c00082 (15/130)
scn: 0x0000.0225a6cb seq: 0x01 flg: 0x04 tail: 0xa6cb2301
frmt: 0x02 chkval: 0xbaf6 type: 0x23=PAGETABLE SEGMENT HEADER
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00007F193760EA00 to 0x00007F1937610A00
7F193760EA00 0000A223 03C00082 0225A6CB 04010000 [#.........%.....]
7F193760EA10 0000BAF6 00000000 00000000 00000000 [................]
7F193760EA20 00000000 00000001 00000008 00000A9C [................]
7F193760EA30 00000000 00000008 00000008 03C00088 [................]
7F193760EA40 00000000 00000000 00000000 00000005 [................]
7F193760EA50 00000000 00000000 00000000 00000000 [................]
7F193760EA60 00000008 00000008 03C00088 00000000 [................]
7F193760EA70 00000000 00000000 00000005 03C00080 [................]
7F193760EA80 03C00080 00000000 00000000 00000000 [................]
7F193760EA90 00000000 00000000 00000000 00000000 [................]
Repeat 3 times
7F193760EAD0 00000001 00002000 00000000 00001434 [..... ......4...]
7F193760EAE0 00000000 03C00081 00000001 03C00080 [................]
7F193760EAF0 03C00081 00000000 00000000 00000000 [................]
7F193760EB00 00000000 00000000 00000001 00000000 [................]
7F193760EB10 0002135A 10000000 03C00080 00000008 [Z...............]
7F193760EB20 00000000 00000000 00000000 00000000 [................]
Repeat 152 times
7F193760F4B0 03C00080 03C00083 00000000 00000000 [................]
7F193760F4C0 00000000 00000000 00000000 00000000 [................]
Repeat 151 times
7F193760FE40 00000000 00000000 03C00081 00000000 [................]
7F193760FE50 00000000 00000000 00000000 00000000 [................]
Repeat 185 times
7F19376109F0 00000000 00000000 00000000 A6CB2301 [.............#..]
Extent Control Header
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 8
last map 0x00000000 #maps: 0 offset: 2716
Highwater:: 0x03c00088 ext#: 0 blk#: 8 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 5
mapblk 0x00000000 offset: 0
Unlocked
Low HighWater Mark :
Highwater:: 0x03c00088 ext#: 0 blk#: 8 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 5
mapblk 0x00000000 offset: 0
Level 1 BMB for High HWM block: 0x03c00080
Level 1 BMB for Low HWM block: 0x03c00080
Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
L2 Array start offset: 0x00001434
First Level 3 BMB: 0x00000000
L2 Hint for inserts: 0x03c00081
Last Level 1 BMB: 0x03c00080
Last Level II BMB: 0x03c00081
Last Level III BMB: 0x00000000
Map Header:: next 0x00000000 #extents: 1 obj#: 136026 flag: 0x10000000
Inc # 0
Extent Map
0x03c00080 length: 8
Auxillary Map
Extent 0 : L1 dba: 0x03c00080 Data dba: 0x03c00083
Second Level Bitmap block DBAs
DBA 1: 0x03c00081
End dump data blocks tsn: 17 file#: 15 minblk 130 maxblk 130
该dump数据包含了高水位信息、块位图信息等。
4、truncate前后用解析工具得到的数据
[[email protected] jiexi]$ ./header
kkkkkkk=130 <====代表段头数据在130块
objectid=136026 <====对象号是136026
address 3c00080 8 <====该对象包含的extent和对应的区长度
addrend
rdba=3c00086 <====真正的数据块地址,包含在了 address 3c00080 和3c00080+8之间,说明下面的内容属于对象136026
columns_count=1 <====真正的数据内容,该对象只有1列
c10c
columns_count=1
c10b
[[email protected] jiexi]$
SQL> alter system switch logfile;
System altered.
SQL> col member for a50
SQL> select l.member from v$logfile l, v$log g where l.group#=g.group# and g.status=‘CURRENT‘;
MEMBER
/u01/app/oradata/QXY/redo02.log
SQL>
<======做truncate操作
SQL> select * from pygc;
ID
10
11
SQL> truncate table pygc;
Table truncated.
SQL> select * from pygc;
no rows selected
SQL>
[[email protected] jiexi]$
[[email protected] jiexi]$ ./header <=====第二次解析
kkkkkkk=130
objectid=136027 <======解析之后发现对象号从136026变成了136027
address 3c00080 8
addrend
rdba=3c00086
columns_count=1
c10c
columns_count=1
c10b
[[email protected] jiexi]$
这里不介绍把raw数据怎么结合解析system表空间数据文件得到数据转换成对应的表。可以参考之前写的文章。
truncate之后,object_id和data_object_id的值就不一样了,如下:
SQL> select object_id, data_object_id, object_name from dba_objects where object_name=‘PYGC‘;
OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
136026 136027 PYGC
SQL>
5、再做一次段头块dump
SQL> alter system dump datafile 15 block 130;
System altered.
SQL> select value from v$diag_info where name = ‘Default Trace File‘;
VALUE
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_4925.trc
SQL>
buffer tsn: 17 rdba: 0x03c00082 (15/130)
scn: 0x0000.0225a8a2 seq: 0x01 flg: 0x04 tail: 0xa8a22301
frmt: 0x02 chkval: 0x8c34 type: 0x23=PAGETABLE SEGMENT HEADER
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00007FC77D732A00 to 0x00007FC77D734A00
7FC77D732A00 0000A223 03C00082 0225A8A2 04010000 [#.........%.....]
7FC77D732A10 00008C34 00000000 00000000 00000000 [4...............]
7FC77D732A20 00000000 00000001 00000008 00000A9C [................]
7FC77D732A30 00000000 00000003 00000008 03C00083 [................]
7FC77D732A40 00000000 00000000 00000000 00000000 [................]
7FC77D732A50 0014001B 000036CD 00000001 00000000 [.....6..........]
7FC77D732A60 00000003 00000008 03C00083 00000000 [................]
7FC77D732A70 00000000 00000000 00000000 03C00080 [................]
7FC77D732A80 03C00080 00000000 00000000 00000000 [................]
7FC77D732A90 00000000 00000000 00000000 00000000 [................]
Repeat 3 times
7FC77D732AD0 00000001 00002000 00000000 00001434 [..... ......4...]
7FC77D732AE0 00000000 03C00081 00000001 03C00080 [................]
7FC77D732AF0 03C00081 00000000 00000000 00000000 [................]
7FC77D732B00 00000000 00000000 00000001 00000000 [................]
7FC77D732B10 0002135B 10000000 03C00080 00000008 [[...............]
7FC77D732B20 00000000 00000000 00000000 00000000 [................]
Repeat 152 times
7FC77D7334B0 03C00080 03C00083 00000000 00000000 [................]
7FC77D7334C0 00000000 00000000 00000000 00000000 [................]
Repeat 151 times
7FC77D733E40 00000000 00000000 03C00081 00000000 [................]
7FC77D733E50 00000000 00000000 00000000 00000000 [................]
Repeat 185 times
7FC77D7349F0 00000000 00000000 00000000 A8A22301 [.............#..]
Extent Control Header
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 8
last map 0x00000000 #maps: 0 offset: 2716
Highwater:: 0x03c00083 ext#: 0 blk#: 3 ext size: 8 <===和truncate之前对比发现,高水位发生了变化
#blocks in seg. hdr‘s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Disk Lock:: Locked by xid: 0x001b.014.000036cd
Low HighWater Mark :
Highwater:: 0x03c00083 ext#: 0 blk#: 3 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Level 1 BMB for High HWM block: 0x03c00080
Level 1 BMB for Low HWM block: 0x03c00080
Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
L2 Array start offset: 0x00001434
First Level 3 BMB: 0x00000000
L2 Hint for inserts: 0x03c00081
Last Level 1 BMB: 0x03c00080
Last Level II BMB: 0x03c00081
Last Level III BMB: 0x00000000
Map Header:: next 0x00000000 #extents: 1 obj#: 136027 flag: 0x10000000
Inc # 0
Extent Map
0x03c00080 length: 8
Auxillary Map
Extent 0 : L1 dba: 0x03c00080 Data dba: 0x03c00083
Second Level Bitmap block DBAs
DBA 1: 0x03c00081
End dump data blocks tsn: 17 file#: 15 minblk 130 maxblk 130
可以发现truncate前后,高位数的数据发生了变化,offset 272位置标记object_id的值从原来的136026(0002135A)变成了136027(0002135B?), truncate之前的高水位的地址为0x03c00088,并且高水位在0号区的第8个块的位置。
? truncate之后高水位的地址为0x03c00083,并且高水位在0号区的第3个块上面。
6、truncate之后做数据块的dump
SQL> alter system dump datafile 15 block 134;
System altered.
SQL> select value from v$diag_info where name = ‘Default Trace File‘;
VALUE
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_4951.trc
SQL>
buffer tsn: 17 rdba: 0x03c00086 (15/134)
scn: 0x0000.0225a6ce seq: 0x01 flg: 0x06 tail: 0xa6ce0601
frmt: 0x02 chkval: 0x8361 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00007FCD7A101A00 to 0x00007FCD7A103A00
7FCD7A101A00 0000A206 03C00086 0225A6CE 06010000 [..........%.....]
7FCD7A101A10 00008361 00000001 0002135A 0225A6CB [a.......Z.....%.]
7FCD7A101A20 00000000 0032F802 03C00080 00010017 [......2.........]
7FCD7A101A30 00002CD0 04C023C2 00060593 00002002 [.,...#....... ..]
7FCD7A101A40 0225A6CE 00000000 00000000 00000000 [..%.............]
7FCD7A101A50 00000000 00000000 00000000 00000000 [................]
7FCD7A101A60 00000000 00020100 0016FFFF 1F701F8C [..............p.]
7FCD7A101A70 00001F70 1F920002 00001F8C 00000000 [p...............]
7FCD7A101A80 00000000 00000000 00000000 00000000 [................]
Repeat 502 times
7FCD7A1039F0 0201012C 012C0CC1 0BC10201 A6CE0601 [,.....,.........]
Block header dump: 0x03c00086
Object id on Block? Y
seg/obj: 0x2135a csc: 0x00.225a6cb itc: 2 flg: E typ: 1 - DATA
brn: 0 bdba: 0x3c00080 ver: 0x01 opc: 0
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0017.001.00002cd0 0x04c023c2.0593.06 --U- 2 fsc 0x0000.0225a6ce
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
bdba: 0x03c00086
data_block_dump,data header at 0x7fcd7a101a64
tsiz: 0x1f98
hsiz: 0x16
pbl: 0x7fcd7a101a64
76543210
flag=--------
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x1f8c
avsp=0x1f70
tosp=0x1f70
0xe:pti[0] nrow=2 offs=0
0x12:pri[0] offs=0x1f92
0x14:pri[1] offs=0x1f8c
block_row_dump:
tab 0, row 0, @0x1f92
tl: 6 fb: --H-FL-- lb: 0x1 cc: 1
col 0: [ 2] c1 0b
tab 0, row 1, @0x1f8c
tl: 6 fb: --H-FL-- lb: 0x1 cc: 1
col 0: [ 2] c1 0c
end_of_block_dump
End dump data blocks tsn: 17 file#: 15 minblk 134 maxblk 134
truncate前后,数据块中的数据还是两行,可以理解为数据并没有被删除。(这个时候这个数据块是可以被覆盖的,因为当前块已经不属于任意段头块中的区范围)
7、修改obj$
SQL> desc obj$
Name Null? Type
OBJ# NOT NULL NUMBER
DATAOBJ# NUMBER
OWNER# NOT NULL NUMBER
NAME NOT NULL VARCHAR2(30)
NAMESPACE NOT NULL NUMBER
SUBNAME VARCHAR2(30)
TYPE# NOT NULL NUMBER
CTIME NOT NULL DATE
MTIME NOT NULL DATE
STIME NOT NULL DATE
STATUS NOT NULL NUMBER
REMOTEOWNER VARCHAR2(30)
LINKNAME VARCHAR2(128)
FLAGS NUMBER
OID$ RAW(16)
SPARE1 NUMBER
SPARE2 NUMBER
SPARE3 NUMBER
SPARE4 VARCHAR2(1000)
SPARE5 VARCHAR2(1000)
SPARE6 DATE
SQL> select obj#,DATAOBJ#,NAME from obj$ where obj#=136026;
OBJ# DATAOBJ# NAME
136026 136027 PYGC
SQL>
和dba_objects视图查到的结果一致
SQL> select object_id, data_object_id, object_name from dba_objects where object_name=‘PYGC‘;
OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
136026 136027 PYGC
SQL>
SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid), dbms_rowid.ROWID_BLOCK_NUMBER(rowid) from obj$ where obj#=136026;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
1 82466
SQL> alter system dump datafile 1 block 82466;
System altered.
SQL> select value from v$diag_info where name = ‘Default Trace File‘;
VALUE
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_4996.trc
SQL>
把OBJECT_ID=136026转换成raw格式,然后在82466块的trace中查询位置
SQL> select utl_raw.CAST_FROM_NUMBER(136026) from dual;
UTL_RAW.CAST_FROM_NUMBER(136026)
C30E3D1B
SQL>
SQL> select utl_raw.CAST_FROM_NUMBER(136027) from dual;
UTL_RAW.CAST_FROM_NUMBER(136027)
C30E3D1C
SQL>
即136026 = c3 0e 3d 1b
136027 = c3 0e 3d 1c
在文件/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_4996.trc中查询对应的数据在row=69(这个数据和obj$对应)
tab 0, row 69, @0x424
tl: 67 fb: --H-FL-- lb: 0x1 cc: 18
col 0: [ 4] c3 0e 3d 1b <===obj#
col 1: [ 4] c3 0e 3d 1c <===dataobj#
col 2: [ 1] 80
col 3: [ 4] 50 59 47 43 <===name
col 4: [ 2] c1 02
col 5: NULL
col 6: [ 2] c1 03
col 7: [ 7] 78 77 06 0a 10 12 26
col 8: [ 7] 78 77 06 0a 10 24 25
col 9: [ 7] 78 77 06 0a 10 12 26
col 10: [ 2] c1 02
col 11: NULL
col 12: NULL
col 13: [ 1] 80
col 14: NULL
col 15: [ 2] c1 07
col 16: [ 2] c1 02
col 17: [ 1] 80
把name=50 59 47 43 转换成varchar2
SQL> select displayraw(‘50594743‘,‘VARCHAR2‘) from dual;
DISPLAY_RAW(‘50594743‘,‘VARCHAR2‘)
PYGC
SQL>
现在就用bbed,把dataobj#=136027 改成 136026
BBED> info all
File# Name Size(blks)
1 /u01/app/oradata/QXY/system01.dbf 0
2 /u01/app/oradata/QXY/sysaux01.dbf 0
3 /u01/app/oradata/QXY/untbs1.dbf 0
4 /u01/app/oradata/QXY/users01.dbf 0
5 /u01/app/oradata/QXY/example01.dbf 0
6 /u01/app/oradata/QXY/OGG.dbf 0
7 /u01/app/oradata/test.dbf 0
8 /u01/app/oradata/QXY/corrupt.dbf 0
9 /u01/app/oradata/QXY/utb1.dbf 0
10 /u01/app/oradata/QXY/undotbs03.dbf 0
11 /u01/app/oradata/QXY/streams_tbs01.dbf 0
12 /u01/app/oradata/QXY/chenhao01.dbf 0
13 /u01/app/oradata/QXY/t.dbf 0
14 /u01/app/oradata/QXY/xxx.dbf 0
15 /u01/app/oradata/QXY/py.dbf 0
BBED>
BBED> set dba 1,82466
DBA 0x00414222 (4276770 1,82466)
BBED> map
File: /u01/app/oradata/QXY/system01.dbf (1)
Block: 82466 Dba:0x00414222
KTB Data Block (Table/Cluster)
struct kcbh, 20 bytes @0
struct ktbbh, 72 bytes @20
struct kdbh, 14 bytes @92
struct kdbt[1], 4 bytes @106
sb2 kdbr[72] @110
ub1 freespace[898] @254
ub1 rowdata[7036] @1152
ub4 tailchk @8188
BBED> p *kdbr[69] <======从dump中可以知道在row=69
rowdata[0]
ub1 rowdata[0] @1152 0x2c
BBED>
BBED> d
File: /u01/app/oradata/QXY/system01.dbf (1)
Block: 82466 Offsets: 1152 to 1663 Dba:0x00414222
2c011204 c30e3d1b 04c30e3d 1c018004 50594743 02c102ff 02c10307 7877060a
10122607 7877060a 10242507 7877060a 10122602 c102ffff 0180ff02 c10702c1
0201802c 001204c3 0e3d1804 c30e3d18 01800358 414202c1 02ff02c1 03077877
060a0c20 25077877 060a0c20 25077877 060a0c20 2502c102 ffff0180 ff02c107
02c10201 803c0112 04c30e3d 1604c30e 3d170180 014302c1 02ff02c1 03077877
060a0b1c 3b077877 060a0b1f 2e077877 060a0b1c 3b02c102 ffff0180 ff02c107
02c10201 803c0112 04c30e3d 1404c30e 3d150180 014302c1 02ff02c1 03077877
060a0b17 01077877 060a0b1a 26077877 060a0b17 0102c102 ffff0180 ff02c107
02c10201 803c0212 04c30e3d 1304c30e 3d130180 014302c1 02ff02c1 03077877
060a0b16 2b077877 060a0b16 2b077877 060a0b16 2b02c102 ffff0180 ff02c107
02c10201 803c0212 04c30e3d 0f04c30e 3d120180 04414243 4402c102 ff02c103
07787706 0a071c08 07787706 0a0b102b 07787706 0a071c08 02c102ff ff0180ff
02c10702 c1020180 3c021204 c30e3d0e 04c30e3d 0e018004 41424344 02c102ff
02c10307 7877060a 05051507 7877060a 05051507 7877060a 05051502 c102ffff
0180ff02 c10702c1 0201803c 011204c3 0e3d0804 c30e3d09 01800642 4c4f434b
3302c102 ff02c103 07787706 060a3927 07787706 060a3a37 07787706 060a3927
<32 bytes per line>
BBED>
现在把c30e3d1c改成c30e3d1b
BBED> set offset +12
OFFSET 1164
BBED> d
File: /u01/app/oradata/QXY/system01.dbf (1)
Block: 82466 Offsets: 1164 to 1675 Dba:0x00414222
1c018004 50594743 02c102ff 02c10307 7877060a 10122607 7877060a 10242507
7877060a 10122602 c102ffff 0180ff02 c10702c1 0201802c 001204c3 0e3d1804
c30e3d18 01800358 414202c1 02ff02c1 03077877 060a0c20 25077877 060a0c20
25077877 060a0c20 2502c102 ffff0180 ff02c107 02c10201 803c0112 04c30e3d
1604c30e 3d170180 014302c1 02ff02c1 03077877 060a0b1c 3b077877 060a0b1f
2e077877 060a0b1c 3b02c102 ffff0180 ff02c107 02c10201 803c0112 04c30e3d
1404c30e 3d150180 014302c1 02ff02c1 03077877 060a0b17 01077877 060a0b1a
26077877 060a0b17 0102c102 ffff0180 ff02c107 02c10201 803c0212 04c30e3d
1304c30e 3d130180 014302c1 02ff02c1 03077877 060a0b16 2b077877 060a0b16
2b077877 060a0b16 2b02c102 ffff0180 ff02c107 02c10201 803c0212 04c30e3d
0f04c30e 3d120180 04414243 4402c102 ff02c103 07787706 0a071c08 07787706
0a0b102b 07787706 0a071c08 02c102ff ff0180ff 02c10702 c1020180 3c021204
c30e3d0e 04c30e3d 0e018004 41424344 02c102ff 02c10307 7877060a 05051507
7877060a 05051507 7877060a 05051502 c102ffff 0180ff02 c10702c1 0201803c
011204c3 0e3d0804 c30e3d09 01800642 4c4f434b 3302c102 ff02c103 07787706
060a3927 07787706 060a3a37 07787706 060a3927 02c102ff ff0180ff 02c10702
<32 bytes per line>
BBED> m /x 1b
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
File: /u01/app/oradata/QXY/system01.dbf (1)
Block: 82466 Offsets: 1164 to 1675 Dba:0x00414222
1b018004 50594743 02c102ff 02c10307 7877060a 10122607 7877060a 10242507
7877060a 10122602 c102ffff 0180ff02 c10702c1 0201802c 001204c3 0e3d1804
c30e3d18 01800358 414202c1 02ff02c1 03077877 060a0c20 25077877 060a0c20
25077877 060a0c20 2502c102 ffff0180 ff02c107 02c10201 803c0112 04c30e3d
1604c30e 3d170180 014302c1 02ff02c1 03077877 060a0b1c 3b077877 060a0b1f
2e077877 060a0b1c 3b02c102 ffff0180 ff02c107 02c10201 803c0112 04c30e3d
1404c30e 3d150180 014302c1 02ff02c1 03077877 060a0b17 01077877 060a0b1a
26077877 060a0b17 0102c102 ffff0180 ff02c107 02c10201 803c0212 04c30e3d
1304c30e 3d130180 014302c1 02ff02c1 03077877 060a0b16 2b077877 060a0b16
2b077877 060a0b16 2b02c102 ffff0180 ff02c107 02c10201 803c0212 04c30e3d
0f04c30e 3d120180 04414243 4402c102 ff02c103 07787706 0a071c08 07787706
0a0b102b 07787706 0a071c08 02c102ff ff0180ff 02c10702 c1020180 3c021204
c30e3d0e 04c30e3d 0e018004 41424344 02c102ff 02c10307 7877060a 05051507
7877060a 05051507 7877060a 05051502 c102ffff 0180ff02 c10702c1 0201803c
011204c3 0e3d0804 c30e3d09 01800642 4c4f434b 3302c102 ff02c103 07787706
060a3927 07787706 060a3a37 07787706 060a3927 02c102ff ff0180ff 02c10702
<32 bytes per line>
BBED> sum apply
Check value for File 1, Block 82466:
current = 0xa9ac, required = 0xa9ac
BBED> verify
DBVERIFY - Verification starting
FILE = /u01/app/oradata/QXY/system01.dbf
BLOCK = 82466
DBVERIFY - Verification complete
Total Blocks Examined : 1
Total Blocks Processed (Data) : 1
Total Blocks Failing (Data) : 0
Total Blocks Processed (Index): 0
Total Blocks Failing (Index): 0
Total Blocks Empty : 0
Total Blocks Marked Corrupt : 0
Total Blocks Influx : 0
Message 531 not found; product=RDBMS; facility=BBED
BBED>
SQL> alter system flush buffer_cache;
System altered.
SQL> alter system flush shared_pool;
System altered.
SQL> select obj#,DATAOBJ#,NAME from obj$ where obj#=136026;
OBJ# DATAOBJ# NAME
136026 136026 PYGC
SQL> select object_id, data_object_id, object_name from dba_objects where object_name=‘PYGC‘;
OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
136026 136026 PYGC
SQL> select count() from pygc; <====但是这个时候查询会报ORA-08103的错误,如下:
select count() from pygc
*
ERROR at line 1:
ORA-08103: object no longer exists
SQL>
SQL>
8、修改tab$
表结构如下:
SQL>
SQL> desc tab$
Name Null? Type
OBJ# NOT NULL NUMBER
DATAOBJ# NUMBER
TS# NOT NULL NUMBER
FILE# NOT NULL NUMBER
BLOCK# NOT NULL NUMBER
BOBJ# NUMBER
TAB# NUMBER
COLS NOT NULL NUMBER
CLUCOLS NUMBER
PCTFREE$ NOT NULL NUMBER
PCTUSED$ NOT NULL NUMBER
INITRANS NOT NULL NUMBER
MAXTRANS NOT NULL NUMBER
FLAGS NOT NULL NUMBER
AUDIT$ NOT NULL VARCHAR2(38)
ROWCNT NUMBER
BLKCNT NUMBER
EMPCNT NUMBER
AVGSPC NUMBER
CHNCNT NUMBER
AVGRLN NUMBER
AVGSPC_FLB NUMBER
FLBCNT NUMBER
ANALYZETIME DATE
SAMPLESIZE NUMBER
DEGREE NUMBER
INSTANCES NUMBER
INTCOLS NOT NULL NUMBER
KERNELCOLS NOT NULL NUMBER
PROPERTY NOT NULL NUMBER
TRIGFLAG NUMBER
SPARE1 NUMBER
SPARE2 NUMBER
SPARE3 NUMBER
SPARE4 VARCHAR2(1000)
SPARE5 VARCHAR2(1000)
SPARE6 DATE
SQL>
查询对象dataobj#=136027在tab$表中的位置
SQL>
SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid), dbms_rowid.ROWID_BLOCK_NUMBER(rowid) from tab$ where obj#=136026;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
1 90285
SQL>
SQL> alter system dump datafile 1 block 90285;
System altered.
SQL> select value from v$diag_info where name = ‘Default Trace File‘;
VALUE
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_5076.trc
SQL>
tab 1, row 1, @0x1a25
tl: 123 fb: -CH-FL-- lb: 0x2 cc: 36 cki: 1
col 0: [ 4] c3 0e 3d 1c <======DATAOBJ# 转换成数字 136027
col 1: [ 2] c1 12
col 2: [ 2] c1 10
col 3: [ 3] c2 02 1f
col 4: NULL
col 5: NULL
col 6: [ 2] c1 02
col 7: NULL
col 8: [ 2] c1 0b
col 9: [ 2] c1 29
col 10: [ 2] c1 02
col 11: [ 3] c2 03 38
col 12: [ 2] c1 02
col 13: [38]
2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d
2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d
col 14: NULL
col 15: NULL
col 16: NULL
col 17: NULL
col 18: NULL
col 19: NULL
col 20: NULL
col 21: NULL
col 22: NULL
col 23: NULL
col 24: NULL
col 25: NULL
col 26: [ 2] c1 02
col 27: [ 2] c1 02
col 28: [ 6] c5 06 25 58 0a 0d
col 29: [ 1] 80
col 30: [ 3] c2 08 25
col 31: NULL
col 32: NULL
col 33: NULL
col 34: NULL
col 35: [ 7] 78 77 06 0a 08 24 24
8、使用bbed把136027 修改成136026, 也就是把c3 0e 3d 1c 修改成c3 0e 3d 1b
BBED> d
File: /u01/app/oradata/QXY/system01.dbf (1)
Block: 90285 Offsets: 6790 to 7301 Dba:0x004160ad
c30e3d1c 02c11202 c11003c2 021fffff 02c102ff 02c10b02 c12902c1 0203c203
3802c102 262d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d
2d2d2d2d 2d2d2d2d 2d2d2dff ffffffff ffffffff ffffff02 c10202c1 0206c506
25580a0d 018003c2 0825ffff ffff0778 77060a08 2424ac00 01020002 00004160
ad000100 4160ad00 0104c30e 3d1b6c00 140002c1 1602c116 02c10801 80065350
41524536 02c10d02 c1080180 ffff0180 ffff02c1 16018001 80018001 80018001
806c0014 0002c115 02c11502 c20b0180 06535041 52453502 c10202c2 0b0180ff
ff0180ff ff02c115 018003c2 093502c1 02018001 8002c20b 6c001400 02c11402
c11402c2 0b018006 53504152 453402c1 0202c20b 0180ffff 0180ffff 02c11401
8003c209 3502c102 01800180 02c20b6c 00140002 c11302c1 1302c117 01800653
50415245 3302c103 02c11701 80ffff01 80ffff02 c1130180 01800180 01800180
01806c00 140002c1 1202c112 02c11701 80065350 41524532 02c10302 c1170180
ffff0180 ffff02c1 12018001 80018001 80018001 806c0014 0002c111 02c11102
c1170180 06535041 52453102 c10302c1 170180ff ff0180ff ff02c111 01800180
01800180 01800180 6c001400 02c11002 c11002c1 11018004 4f494424 02c11802
c1110180 ffff0180 ffff02c1 10018001 80018001 80018001 806c0014 0002c10f
<32 bytes per line>
BBED> set offset +3
OFFSET 6793
BBED> m /x 1b
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
File: /u01/app/oradata/QXY/system01.dbf (1)
Block: 90285 Offsets: 6793 to 7304 Dba:0x004160ad
1b02c112 02c11003 c2021fff ff02c102 ff02c10b 02c12902 c10203c2 033802c1
02262d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d
2d2d2d2d 2d2d2d2d ffffffff ffffffff ffffffff 02c10202 c10206c5 0625580a
0d018003 c20825ff ffffff07 7877060a 082424ac 00010200 02000041 60ad0001
004160ad 000104c3 0e3d1b6c 00140002 c11602c1 1602c108 01800653 50415245
3602c10d 02c10801 80ffff01 80ffff02 c1160180 01800180 01800180 01806c00
140002c1 1502c115 02c20b01 80065350 41524535 02c10202 c20b0180 ffff0180
ffff02c1 15018003 c2093502 c1020180 018002c2 0b6c0014 0002c114 02c11402
c20b0180 06535041 52453402 c10202c2 0b0180ff ff0180ff ff02c114 018003c2
093502c1 02018001 8002c20b 6c001400 02c11302 c11302c1 17018006 53504152
453302c1 0302c117 0180ffff 0180ffff 02c11301 80018001 80018001 8001806c
00140002 c11202c1 1202c117 01800653 50415245 3202c103 02c11701 80ffff01
80ffff02 c1120180 01800180 01800180 01806c00 140002c1 1102c111 02c11701
80065350 41524531 02c10302 c1170180 ffff0180 ffff02c1 11018001 80018001
80018001 806c0014 0002c110 02c11002 c1110180 044f4944 2402c118 02c11101
80ffff01 80ffff02 c1100180 01800180 01800180 01806c00 140002c1 0f02c10f
<32 bytes per line>
BBED>
BBED>
BBED> sum apply;
Check value for File 1, Block 90285:
current = 0xb3b5, required = 0xb3b5
BBED>
再次查询dba_object视图
SQL> select obj#, dataobj# from tab$ where obj#=136026;
OBJ# DATAOBJ#
136026 136027
SQL> alter system flush buffer_cache;
System altered.
SQL> alter system flush shared_pool;
System altered.
SQL> select obj#, dataobj# from tab$ where obj#=136026;
OBJ# DATAOBJ#
136026 136026
SQL>
可以看到dataobj#的值已经从原来的136027变成了136026。但是查询PYGC还是会报ORA-08103的错误。
SQL> alter system flush buffer_cache;
System altered.
SQL> alter system flush shared_pool;
System altered.
SQL> select obj#, dataobj# from tab$ where obj#=136026;
OBJ# DATAOBJ#
136026 136026
SQL>
SQL> select from pygc;
select from pygc
*
ERROR at line 1:
ORA-08103: object no longer exists
9、修改段头块中的object_id的值,把136027改为136026
修改pygc表的段头信息,在偏移量272的位置是objectid
SQL> col segment_name for a20
SQL> select SEGMENT_NAME,HEADER_FILE,HEADER_BLOCK from dba_segments where segment_name = ‘PYGC‘;
SEGMENT_NAME HEADER_FILE HEADER_BLOCK
PYGC 15 130
BBED> set dba 15,130
DBA 0x03c00082 (62914690 15,130)
BBED> set offset 272
OFFSET 272
BBED> d
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 272 to 783 Dba:0x03c00082
5b130200 00000010 8000c003 08000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
136026转换成10进制是2135A
SQL> select to_char(136026,‘xxxxxxxx‘) from dual;
TO_CHAR(1
2135a
SQL>
现在只需把5b改成5a,也就是把136027改成136026
BBED> m /x 5a
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 272 to 783 Dba:0x03c00082
5a130200 00000010 8000c003 08000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
<32 bytes per line>
BBED> sum apply;
Check value for File 15, Block 130:
current = 0xbaf6, required = 0xbaf6
BBED>
SQL> alter system flush shared_pool;
System altered.
SQL> select * from pygc; <=======查询已经没有报错,但是查询结果没有值。
no rows selected
SQL>
可以看到,这个时候查询PYGC已经不报错了,但是没有值,没有值的原因是段头块中的高水位被修改了。表的数据被屏蔽在了高水位之上,所以查询表得不到任何数据,就把高水位改成truncate之前的。
truncate前后高水位的信息
truncate之前的高水位
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 8
last map 0x00000000 #maps: 0 offset: 2716
Highwater:: 0x03c00088 ext#: 0 blk#: 8 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 5
mapblk 0x00000000 offset: 0
Unlocked
Low HighWater Mark :
Highwater:: 0x03c00088 ext#: 0 blk#: 8 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 5
mapblk 0x00000000 offset: 0
Level 1 BMB for High HWM block: 0x03c00080
Level 1 BMB for Low HWM block: 0x03c00080
truncate之后的高水位信息
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 8
last map 0x00000000 #maps: 0 offset: 2716
Highwater:: 0x03c00083 ext#: 0 blk#: 3 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Disk Lock:: Locked by xid: 0x001b.014.000036cd
Low HighWater Mark :
Highwater:: 0x03c00083 ext#: 0 blk#: 3 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Level 1 BMB for High HWM block: 0x03c00080
Level 1 BMB for Low HWM block: 0x03c00080
可以看到truncate之前的高水位的地址为0x03c00088,并且高水位在0号区的第8个块的位置。
truncate之后高水位的地址为0x03c00083,并且高水位在0号区的第3个块上面。
? ? 这里是因为truncate前后都dump了段头块的信息,现实中根本不会有这样的机会的。 但是可以通过redo来查看truncate前后的信息,方法如下:
SQL> alter system dump logfile ‘/u01/app/oradata/QXY/redo02.log‘;
System altered.
SQL> select value from v$diag_info where name = ‘Default Trace File‘;
VALUE
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_5936.trc
SQL>
REDO RECORD - Thread:1 RBA: 0x00015d.0000000f.0110 LEN: 0x01b8 VLD: 0x01
SCN: 0x0000.0225a89c SUBSCN: 6 06/10/2019 15:35:36
CHANGE #1 TYP:0 CLS:70 AFN:19 DBA:0x04c01287 OBJ:4294967295 SCN:0x0000.0225a89c SEQ:2 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 164 spc: 7536 flg: 0x0022 seq: 0x0611 rec: 0x06
xid: 0x001b.014.000036cd
ktubu redo: slt: 20 rci: 5 opc: 13.29 objn: 136026 objd: 136026 tsn: 17
Undo type: Regular undo Undo type: Last buffer split: No
Tablespace Undo: No
0x00000000
Segment Header Undo
Seghdr dba: 0x03c00082 Mapblock dba: 0x00000000 Mapredo Offset: 4 scls: 4 mcls: 140668768878599
Both the HWMs
Low HWM
Highwater:: 0x03c00088 ext#: 0 blk#: 8 ext size: 8 <=====高水位信息,包含地址、高水位所在的区、块、区包含的块
#blocks in seg. hdr‘s freelists: 0
#blocks below: 5 <=====高水位下面包含5个块
mapblk 0x00000000 offset: 0
lfdba: 0x03c00080
High HWM
Highwater:: 0x03c00088 ext#: 0 blk#: 8 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 5
mapblk 0x00000000 offset: 0
lfdba: 0x03c00080 hint dba: 0x03c00081
Lasts in Header
LF: 62914688 LS: 62914689 LT: 0 FT: 0
CHANGE #2 TYP:0 CLS:4 AFN:15 DBA:0x03c00082 OBJ:136026 SCN:0x0000.0225a89c SEQ:1 OP:13.28 ENC:0 RBL:0 <====truncate操作
Both the HWMs
Low HWM
Highwater:: 0x03c00083 ext#: 0 blk#: 3 ext size: 8 <====truncate之后的高水位信息
#blocks in seg. hdr‘s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
lfdba: 0x03c00080
High HWM
Highwater:: 0x03c00083 ext#: 0 blk#: 3 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
lfdba: 0x03c00080 hint dba: 0x03c00081
Lasts in Header
LF: 62914688 LS: 62914689 LT: 0 FT: 0
CHANGE #3 TYP:0 CLS:8 AFN:15 DBA:0x03c00080 OBJ:136026 SCN:0x0000.0225a89c SEQ:2 OP:13.22 ENC:0 RBL:0
Redo on Level1 Bitmap Block
Redo to set hwm
Opcode: 32 Highwater:: 0x03c00083 ext#: 0 blk#: 3 ext size: 8
#blocks in seg. hdr‘s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
dump logfile得到的数据和dump 段头块的高水位数据一致。
10、使用bbed修改段头块中的高水位信息
BBED> set dba 15,130
DBA 0x03c00082 (62914690 15,130)
BBED> set offset 52
OFFSET 52
BBED> d /v count 16
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 52 to 67 Dba:0x03c00082
03000000 08000000 8300c003 00000000 l ................
<16 bytes per line>
BBED> m /x 08 <======把高水所在0号区的块从3改成8
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 52 to 67 Dba:0x03c00082
08000000 08000000 8300c003 00000000
<32 bytes per line>
BBED>
BBED> d /v count 16
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 60 to 75 Dba:0x03c00082
8300c003 00000000 00000000 00000000 l ................
<16 bytes per line>
BBED> m /x 88 <======0x03c00083改成0x03c00088
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 60 to 75 Dba:0x03c00082
8800c003 00000000 00000000 00000000
<32 bytes per line>
BBED>
<====同样的道理,修改Low HighWater Mark的值
BBED> set offset 96
OFFSET 96
BBED> d
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 96 to 111 Dba:0x03c00082
03000000 08000000 8300c003 00000000
<32 bytes per line>
BBED> m /x 08
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 96 to 111 Dba:0x03c00082
08000000 08000000 8300c003 00000000
<32 bytes per line>
BBED> set offset +8
OFFSET 104
BBED> d
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 104 to 119 Dba:0x03c00082
8300c003 00000000 00000000 00000000
<32 bytes per line>
BBED> m /x 88
File: /u01/app/oradata/QXY/py.dbf (15)
Block: 130 Offsets: 104 to 119 Dba:0x03c00082
8800c003 00000000 00000000 00000000
<32 bytes per line>
BBED> sum apply;
Check value for File 15, Block 130:
current = 0xbaf6, required = 0xbaf6
BBED>
再次查询表pygc的数据就可以看到被truncate之前的数据了
SQL> alter system flush buffer_cache;
System altered.
SQL> alter system flush shared_pool;
System altered.
SQL> select * from pygc;
ID
10
11
SQL>
但是现在有一个问题,就是pygc这个表无法drop和insert。如果该表需要继续使用,需要使用CTAS的方式创建一个新表。具体报错如下:
SQL> drop table pygc;
drop table pygc
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 2
ORA-08102: index key not found, obj# 39, file 1, block 62284 (2)
SQL>
SQL> insert into pygc select from pygc;
insert into pygc select from pygc
*
ERROR at line 1:
ORA-00600: internal error code, arguments: [ktspgfblk3:kcbz_objdchk], [0], [0],
[1], [], [], [], [], [], [], [], []
SQL>
如果需要drop该表,需要把修改obj$、tab$中修改的数据改回去。然后就可以drop掉,这里就不在演示,已经测试可以drop。
所以,表被truncate之后,表就会回收高水位,这样之前的数据就会被放到高水位之上,再次查询该表的时候就无记录返回。同时高水位之前的数据可以被其他需要分配块的操作占用。如果数据块被占用,则占用的数据是无法恢复的。上面的整个过程就是演示了truncate操作的原理。真正恢复数据的时候还是用DRT恢复工具恢复会方便很多,如果数据量很大,并且数据没有被覆盖,修改元数据会更快的恢复数据,但是这种方式存在风险,因为无法全部知道oracle更新了什么操作。 如果发现表被误操作,尽可能不要在操作DML,或者把表对应的表空间设置为read only模式,这样恢复数据的概率就会更高。
原文地址:https://blog.51cto.com/14523150/2436544