日志文章

2007年10月22日 13:26:53

DUMPING ORACLE BLOCKS<1>

Brian Peasland, Raytheon at EROS Data Center


在网上看见这篇文章,我简单的翻译了一下。






Introduction
实际上,需要我们dump Oracle的数据块的CASE是很少见。这些块包括表、索引甚至是控制文件。当我们查询一个表的内容时候,我们可能会思考表的内部有什么奥秘,而不仅仅满足于查询返回的。本文将讨论如何dump数据块,解释dump出的内容。

Why Dump Blocks?
但我们还是要问,为什么要这样做呢?很大程度上,这是取决于你的好奇心。尤其是作为一个DBA,要具备强烈的好奇心。Oracle并没有的开放其数据块的内核,仅仅稍微透露的一些信息,这样更加让我们好奇。因而,大多数情况下,dump只是一种试验,不过也许在一些CASE中,我们也可以利用塔找到有价值的东西。总之,对我们来说,它是一种有意思的事情。



Trace File Information



本文所有的例子都是生成的trace文件,参考参数USER_DUMP_DEST用于找到它。通过下面的查询,可以确定trace文件的生成。

ORA9I SQL> select pa.value || '/' || i.instance_name || '_ora_'
2     || pr.spid || '.trc' as trace_file
3 from v$session s, v$process pr, v$parameter pa, v$instance i
4 where s.username = user and s.paddr = pr.addr
5* and pa.name='user_dump_dest';


TRACE_FILE

------------------------------------------------------------------------
/edcsns14/pkg/oracle/admin/ora9i/udump/ora9i_ora_25199.trc


这个查询显示我的会话的trace文件的完整路径和文件名,这个文本文件中将显示出我们dump的内容。



所有的trace文件头包含同样的基本信息:



Oracle9i Enterprise Edition Release 9.0.1.0.0 - Production

With the Partitioning option
JServer Release 9.0.1.0.0 - Production
ORACLE_HOME = /edcsns14/pkg/oracle/9.0.1
System name:   SunOS
Node name:   edcsns14
Release:   5.7
Version:   Generic_106541-11
Machine:   sun4u
Instance name: ora9i
Redo thread mounted by this instance: 1
Oracle process number: 11
Unix process pid: 653, image: oracle@edcsns14 (TNS V1-V3)


*** 2002-03-27 17:06:06.573

*** SESSION ID:(12.4240) 2002-03-27 17:06:06.535


每个trace文件头的输出都类似。这个输出显示数据库的版本,一些平台信息诸如主机名,OS等级,数据库实例名,会话的进程标识(OracleUnix)以及时间。这些信息我们简略介绍至此。



Dumping A Table Block

为了导出一个表的某一数据库,你需要知道文件号和块号。如果你已经知道了,那就准备就绪。

ORA9I SQL> select file_id,block_id,bytes,blocks
2 from dba_extents
3 where owner='PEASLAND' and segment_name='EMP';


FILE_ID   BLOCK_ID       BYTES   BLOCKS

------- ---------- ---------------- --------
  3     9     65,536   8
这里,我查询了一个数据字典表用于查寻我的EMP表的物理位置。EMP表在3号文件中,起始数据块是9,然后它包含8个数据块。这个查寻对每个段将返回一行。如果这个对象是有很多盘区组成,我能检查表空间是否属于当前文件,通过以下查寻:

ORA9I SQL> select tablespace_name,file_name from dba_data_files
2 where relative_fno = 3;


TABLESPACE_NAME       FILE_NAME

------------------------------ -----------------------------------------
USER_DATA           /edcsns14/oradata3/ora9i/user_data01.dbf
正如我希望的一样,我的表在USER_DATE表空间中。

现在,让我们来dump一个块吧,操作如下:

ORA9I SQL> alter system dump datafile 3 block 10;


System altered.



你也可以导出一个范围的数据块:

ORA9I SQL> alter system dump datafile 3 block min 10 block max 12;


System altered.



下面我们来查看导出的内容:

Start dump data blocks tsn: 3 file#: 3 minblk 10 maxblk 10
buffer tsn: 3 rdba: 0x00c0000a (3/10)
scn: 0x0000.00046911 seq: 0x02 flg: 0x04 tail: 0x69110602
frmt: 0x02 chkval: 0x579d type: 0x06=trans data
Block header dump: 0x00c0000a
Object id on Block? Y
seg/obj: 0x6d9c csc: 0x00.46911 itc: 2 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01

Itl     Xid         Uba     Flag Lck   Scn/Fsc

0x01   xid: 0x0005.02f.0000010c   uba: 0x00806f10.00ca.28 C---   0 scn 0x0000.00046900
0x02   xid: 0x0003.01c.00000101   uba: 0x00800033.0099.04 C---   0 scn 0x0000.00046906


这是一个数据块dump信息的开始部分。第一行告诉我们,该块是来自是文件3,起始块是#10,终止块也是#10。我们也可以导出一个范围的块。数据块的地址是0x00c0000a。(3/10)指的文件3,第10号块。

第三行是数据块的SCN。在这个例子里,SCN0x0000.00046911。而tail是由SCN的后两个byte6911),再加上类型(06)和序列(02)。如果tail的分解和SCN不符合了,那么就需要恢复。这个tail的值是显示在dump信息的开头,但是它实际是存储在数据块的结尾的。

第四行是数据块的类型,请参考如下列表:

Type   Meaning      
0x02   undo block
0x06 table or index data block
0x0e undo segment header
0x10   data segment header block
0x17   bitmapped data segment header



Object id on Block?这句话告诉我们这个对象是否在SYS.OBJ$里。从Oracle6开始,这里就一直是Y。继续看下一行,seg/obj的值告诉我们段的对象id16进制)。我们能够用下面的查寻校验它是否属于我们的表。28060是转换后10进制的值。



ORA9I SQL> select owner,object_name from dba_objects

2 where object_id=28060;


OWNER   OBJECT_NAME

---------- ------------------------------
PEASLAND   EMP


Csc的值是清除SCN的值,这个值告诉我们块的清除是什么时候发生的。它和块的SCN是一致的。Itc的值是事务链表统计。在这个例子里,有两个事务访问这个块。这些事务是在我们的例子外执行的。我们能够看到它们的事务idXid)。这些事务标识起着和回滚段类似的作用。



Flagflg)要么是“-”要么是“O”,用于表示这个块是否在freelist上。如果在,那么就是O

好了,接下来有更多的信息等着我们的解读。



data_block_dump

===============
tsiz: 0x1fa0
hsiz: 0x2e
pbl: 0x024d015c
bdba: 0x00c0000a
flag=-------------
ntab=1
nrow=14
frre=9
fsbo=0x2e
fseo=0x1b18
avsp=0x1d8a
tosp=0x1d8a
0xe:pti[0]   nrow=14 offs=0
0x12:pri[0]   offs=0x1c30
0x14:pri[1]   offs=0x1f4f
0x16:pri[2]   offs=0x1f24
0x18:pri[3]   offs=0x1efb
0x1a:pri[4]   offs=0x1ece
0x1c:pri[5]   offs=0x1ea5
0x1e:pri[6]   offs=0x1e7c
0x20:pri[7]   offs=0x1e54
0x22:pri[8]   offs=0x1e2e
0x24:pri[9]   sfll=13
0x26:pri[10]   offs=0x1ca4
0x28:pri[11]   offs=0x1cf1
0x2a:pri[12]   offs=0x1b18
0x2c:pri[13]   sfll=-1
Tsiz值给我们显示了当前数据块的可用空间。这里,我们1fa0就是指8096byte可用。另外在一个块里面,有一些空间是用于块头的。



Ntab值显示有多少个表存储在这个块里面。不过,除非这个块是一个集群表,否则它就是1.nrow显示有多少行,在这里有14行。



开始地址是‘0xe’,每一行都有一个目录。我们可用看见第一行(索引0)起始的offset address ‘0x1c30’。块里面的每一行都按这样排列。这样,能够很快的找到某一行。在Oracle8+,ROWID是由O.F.B.R组(objectno,relativefno,blockno,rowno



现在我们对数据块有一个初步认识,我们来看trace file 中剩余的部分。



block_row_dump:

tab 0, row 0, @0x1c30
tl: 39 fb: --H-FL-- lb: 0x0 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: [ 3] c2 09 19
col 6: *NULL*
col 7: [ 2] c1 15
实际的行是从block_row_dump:开始出现的,也就是块中存储的实际数据。我们这里只列出了一行。我们可以看出这行属于table0.

T1值告诉我们这个行有多少个byte,包含一些额外的开销。这一行占用39byte。‘cc’的值表明有多少个字段。


Fb值是一个标记,H意思是我们在行的头部,F表明这是这行第一块,L表示是最后一块,那就意味着这行记录没有发生行迁移或者行链接。



其余的信息则是数据,例如在第一行,我们有一行ASCII字符编码53 4d 49 54 48”,它的意思就是”SMITH”。如果你查询EMP表,你就知道SMITH是一个雇员的名字。另外,要注意column6是空,column4data类型,它用7byte来存储。


<未完待续>

Tags: dump  

类别: Administer |  评论(0) |  浏览(3827) |  收藏
发表评论