共计 7993 个字符,预计需要花费 20 分钟才能阅读完成。
今天就跟大家聊聊有关如何理解 dump 数据块,可能很多人都不太了解,为了让大家更加了解,丸趣 TV 小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
一、dump 数据文件
dump 数据文件需要知道表的存储信息:数据文件号(file#)和数据块号(block#)。
以下查询表所在的表空间、文件号、区段分布、块分布信息
col segment_name for a20
col tablespace_name for
a20
select
segment_name, segment_type, tablespace_name, extent_id, file_id, block_id,
blocks, bytes from dba_extents where owner = SCOTT and segment_name = EMP
SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME EXTENT_ID FILE_ID
BLOCK_ID BLOCKS BYTES
——————–
—————— ——————– ———- ———- ———-
———- ———-
EMP TABLE USERS 0 4 144 8
65536
再看表记录的块分布信息
select
dbms_rowid.rowid_block_number(rowid) block#, count(*) block_records from scott.emp group by dbms_rowid.rowid_block_number(rowid) order by block#;
BLOCK# BLOCK_RECORDS
———- ————-
151 14
可见表段开始的前几个块是用于存储段头信息的,行记录数据从后面块开始。
使用以下命令可以 dump 一个或多个数据块:
alter system
dump datafile file# block block#
alter system
dump datafile file# block min block#_min block max
block#_max
先看一下当前会话对应的跟踪文件
trace_file_name for a80
select a.value ||
b.symbol || c.instance_name || _ora_ || d.spid ||
.trc trace_file_name
from (select value from v$parameter where
name = user_dump_dest ) a,
(select substr(value, -6, 1) symbol
from v$parameter
where name = user_dump_dest ) b,
(select instance_name from v$instance)
c,
(select spid
from v$session s, v$process p,
v$mystat m
where s.paddr = p.addr
and s.sid = m.sid
and m.statistic# = 0) d;
TRACE_FILE_NAME
———————————————————
c:\oracle\diag\rdbms\mes\mes\trace\mes_ora_3912.trc
现在 dump 文件块
alter system dump
datafile 4 block 151;
查看跟踪文件内容
Start dump data blocks
tsn: 4 file#:4 minblk 151 maxblk 151
Block dump from cache:
Dump of buffer cache at
level 4 for tsn=4, rdba=16777367
Block dump from disk:
buffer tsn: 4 rdba:
0x01000097 (4/151)
scn: 0x0000.001ef9e3 seq:
0x01 flg: 0x06 tail: 0xf9e30601
frmt: 0x02 chkval: 0xd2a5
type: 0x06=trans data
Hex dump of block: st=0,
typ_found=1
Dump of memory from
0x000000000D186E00 to 0x000000000D188E00
00D186E00 0000A206
01000097 001EF9E3 06010000
[…………….]
…
00D188DF0 0101110C
09C20201 15C102FF F9E30601
[…………….]
Block header dump: 0x01000097
Object id on Block? Y
seg/obj: 0x11dec csc: 0x00.1ef9cc itc: 2
flg: E typ: 1 – DATA
brn: 0
bdba: 0x1000090 ver: 0x01 opc: 0
inc: 0
exflg: 0
Itl
Xid Uba Flag
Lck Scn/Fsc
0x01 0x000a.009.0000044c 0x00c00f07.012e.20 –U-
1 fsc 0x0000.001ef9e3
0x02 0x000a.004.0000044d 0x00c00f07.012e.1c C—
0 scn 0x0000.001ef98a
数据块主要信息如下:
tsn:表空间编号
file#:文件编号
minblk 和 maxblk:导出块编号的范围
rdba:相对块地址信息
这里 rdba 列出了十六进制形式和十进制形式,这个地址可以使用如下查询通过文件号和块号进行转换
select
dbms_utility.make_data_block_address(4, 151) from dual;
DBMS_UTILITY.MAKE_DATA_BLOCK_ADDRESS(4,151)
——————————————-
16777367
它的十六进制形式
select
to_char(16777367, xxxxxxxx)
from dual;
TO_CHAR(1
———
1000097
反过来,也可以通过块地址转换得到文件号和块号
select
dbms_utility.data_block_address_file(16777367) file#, dbms_utility.data_block_address_block(16777367) block# from dual;
FILE#
BLOCK#
———- ———-
4 151
scn:数据块的 SCN 信息
tail:由 SCN 的最后两字节、块类型 type 和序列号 seq 组成
Oracle 利用数据块的 tail 来判断数据块内容的一致性,如果这里的 tail 分解后和 SCN 的最后两字节、块类型和序列号三者不匹配,Oracle 可以判断这个块处于不一致状态,需要恢复。这里的 tail 信息虽然显示在块跟踪文件的开始部分,而事实上它物理的存储在数据块的最末端,这也是 tail 名称的由来。
块类型 type 的有效取值有以下几种:
0x02:undo block
0x06:trans data
0x0e:undo segment header
0x10:data segment header block
0x17:bitmapped data segment header
0x20:first level bitmap block
0x21:second level bitmap block
0x23:pagetable segment header
Object
id on Block? Y:数据块上存储的数据库对象是否存在于 sys.obj$ 数据字典
seg/obj:数据库对象的 ID 信息,以下查询可以验证
object_name for a30
select owner,
object_name from dba_objects where object_id = to_number(11dec , xxxxx
OWNER OBJECT_NAME
——————————
——————————
SCOTT EMP
csc:块清理时的 SCN(cleanout SCN),注意观察它是否匹配数据块的 SCN。
itc:事务槽(ITL slot)的数量,下面的两行正是 ITL 的信息,对应两个事务,用 xid 标识。
flag:标识数据块是否存在于段的 freelist,“-”表示该块不在 freelist 中,“o”代表 on,表示该块存在于 freelist,可用于 insert 记录。
以下是数据头部分
data_block_dump,data
header at 0xd186e64
===============
tsiz: 0x1f98
hsiz: 0x2e
pbl: 0x0d186e64
76543210
flag=——–
ntab=1
nrow=14
frre=-1
fsbo=0x2e
fseo=0x1d61
avsp=0x1d33
tosp=0x1d33
0xe:pti[0] nrow=14 offs=0
0x12:pri[0] offs=0x1f72
0x14:pri[1] offs=0x1f47
0x16:pri[2] offs=0x1f1c
0x18:pri[3] offs=0x1ef3
0x1a:pri[4] offs=0x1ec6
0x1c:pri[5] offs=0x1e9d
0x1e:pri[6] offs=0x1e74
0x20:pri[7] offs=0x1e4c
0x22:pri[8] offs=0x1e26
0x24:pri[9] offs=0x1dfb
0x26:pri[10] offs=0x1dd5
0x28:pri[11] offs=0x1daf
0x2a:pri[12] offs=0x1d88
0x2c:pri[13] offs=0x1d61
这里含义如下:
tsiz:数据块用于存储数据部分的总空间(total data area size)
hsiz:头尺寸(header size)
pbl:数据块在缓存中的地址指针(pointer to buffer holding the
block),下面一行则是其块地址 bdba。
ntab:number of tables,如果该值大于 1,说明该数据块属于 cluster 的存储块。
nrow:number of rows,数据块中存储的记录数量。
fsbo、fseo:free space begin offset 和 free space end offset,两者给出了块中自由空间的起始位置。
avsp:available space in the block
tosp:total available space when all transactions
commit
再往后就是行记录信息,以下是第一条记录
block_row_dump:
tab 0, row 0, @0x1f72
tl: 38 fb: –H-FL– lb:
0x1 cc: 8
col 0: [3]
c2 4a 46
col 1: [5]
53 4d 49 54 48
col 2: [5]
43 4c 45 52 4b
col 3: [3]
c2 50 03
col 4: [7]
77 b4 0c 11 01 01 01
col 5: [2]
c2 09
col 6: *NULL*
col 7: [2]
c1 15
这里含义如下:
tab 0,
row 0, @0x1f72:表在 cluster 中的标识、行标识和行地址。
tl:指示该行共占用的字节空间,十进制表示,包含行的其他开销。
fb:行标记,H 表示 head of row,F 和 L 分别表示行的 first piece 和 last
piece,说明此行涉及导出的数据块,不存在行链接,又由于块中存在行头,说明也存在行迁移。
lb:ITL 事务槽编号
cc:列的数量
col n: [k]:第 n + 1 列的数据,占用 k 个字节。
以下验证第二列数据 col 1: [5]
53 4d 49 54 48,数据以十六进制 ASCII 码形式给出,通过以下查询转换为字符
select
chr(to_number( 53 , xx)) || chr(to_number( 4d , xx)) || chr(to_number( 49 ,
xx )) || chr(to_number( 54 , xx)) || chr(to_number( 48 , xx)) from dual;
CHR(TO_NUM
———-
SMITH
或者使用以下程序包转换
serveroutput on
declare c
varchar2(30);
begin
dbms_stats.convert_raw_value(534d495448 , c);
dbms_output.put_line(c);
end;
/
SMITH
对于第一列数据 col 0: [3]
c2 4a 46,该列是 number 类型,可以通过以上程序包转换为十进制数
set serveroutput on
declare n
number;
begin
dbms_stats.convert_raw_value(c24a46 , n);
dbms_output.put_line(n);
end;
/
7369
从 scott.emp 表上可以查询验证,编号为 7369 的员工正是 smith。
对于第五列数据 col 4: [7]
77 b4 0c 11 01 01 01,该列是 date 类型,同样可以通过以上程序包转换为可显示的日期
serveroutput on
declare dt
date;
begin
dbms_stats.convert_raw_value(77b40c11010101 , dt);
dbms_output.put_line(to_char(dt,
yyyy-mm-dd hh34:mi:ss
end;
/
1980-12-17 00:00:00
二、dump 索引文件
索引数据块和表数据块的存储明显不同。一个 b -tree 索引所对应的存储数据块有分支节点块(branch block)和叶节点块(leaf
block)。要导出一个 b -tree 索引,需要提供这个索引的 object_id,为此先查询索引对象及其 ID 信息
col table_name for a30
col tablespace_name for
a20
col index_name for a20
col index_type for a10
select table_name,
index_name, index_type, status, tablespace_name from dba_indexes where
owner= CMES and table_name= C_MATERIAL_T
TABLE_NAME INDEX_NAME INDEX_TYPE STATUS TABLESPACE_NAME
——————————
——————– ———- ——– ——————–
C_MATERIAL_T IDX_FK_MATERIAL_NO NORMAL
VALID CMES
C_MATERIAL_T IDX_FK_PART_NO NORMAL VALID
CMES
C_MATERIAL_T IDX_PK_MATERIAL_ID NORMAL
VALID CMES
select object_id from
dba_objects where object_name = IDX_FK_PART_NO
OBJECT_ID
———-
77043
启用 treedump 事件跟踪来导出,将索引对象的 object_id 代入以下命令
alter session set events
immediate trace name treedump level 77043
查看导出文件
—– begin tree dump
branch: 0x14003b3
20972467 (0: nrow: 2, level: 1)
leaf: 0x14003b4 20972468 (-1: nrow: 322
rrow: 322)
leaf: 0x14003b5 20972469 (0: nrow: 23 rrow:
23)
—– end tree dump
这个索引树只有一个分支节点(branch)也就是索引的根节点(root),块地址为 0x14003b3,其十进制数为 20972467,根节点的 level 为 1,说明该 b -tree 索引的高度为 2,因为索引树的 level 是从 0 开始计的。该根节点下面没有再分支了,就是叶节点块,叶节点的 level 总是 0,因此 dump 文件中不需要标出。分支和叶所在的位置标识从最左边为 - 1 开始而不是 0。对于叶节点块,nrow 表示该节点块中存储的行指针数,对于分支节点块,nrow 表示指向下一层节点的块数。在叶节点块中,还有 rrow,它与块上的事务处理有关(rrow
is the number of rows after all current transactions have been committed),rrow 和 nrow 相等,表示该块涉及的数据上没有正在执行的事务处理。
分析左边第一个叶块 leaf:
0x14003b4 20972468 (-1: nrow: 322 rrow: 322),由数据块地址 dba 转换为对应的文件号、块号
select
dbms_utility.data_block_address_file(to_number( 14003b4 , xxxxxxxx)) file#,
dbms_utility.data_block_address_block(to_number( 14003b4 , xxxxxxxx)) block# from dual;
FILE#
BLOCK#
———- ———-
5 948
dump 该数据块
alter system
dump datafile 5 block 948;
查看 dump 文件,找到叶块的描述部分
Leaf block dump
===============
header address
532770404=0x1fc16e64
kdxcolev 0
KDXCOLEV Flags = – – –
kdxcolok 0
kdxcoopc 0x80: opcode=0:
iot flags=— is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 322
kdxcofbo 680=0x2a8
kdxcofeo 1502=0x5de
kdxcoavs 822
kdxlespl 0
kdxlende 0
kdxlenxt
20972469=0x14003b5
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[8017] flag: ——,
lock: 0, len=19
col 0; len 9; (9): 31 36 44 34 30 37 31 38 33
col 1; len 6; (6): 01 40 03 a5 00 0a
row#1[7997] flag: ——,
lock: 0, len=20
col 0; len 10; (10): 31 38 30 35 30 30 30 34 31 45
col 1; len 6; (6): 01 40 03 9b 00 0c
kdxlenxt:下一个叶节点的块地址
kdxleprv:前一个叶节点的块地址
这两个指针对于 SQL 优化器执行索引的 index
range scans 操作非常重要。随后就是叶块的数据内容,这里只显示了两行记录。
看完上述内容,你们对如何理解 dump 数据块有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注丸趣 TV 行业资讯频道,感谢大家的支持。