本帖最后由 gyj_hobby 于 2012-12-12 10:58 编辑
Data Block是数据库中最小的I/O单元,下面我来简单介绍下数据块的基本结构。 OK!跟着我一步步实验: 一、建表空间 SQL>create tablespace tp1 datafile '/oradata/bxocp/tp01.dbf' size 10M; 二、建用户及授权 SQL>create user gyj identified by gyj default tablespace tp1; SQL>grant dba to gyj; 三、建表 SQL>conn gyj/gyj SQL>create table t1 (id int,name varchar2(100)); 四、插入一行数据 SQL>insert into t1 values(1,'AAAAA'); SQL>commit; 五、手动发生一个检查点,使上面一行数据写到数据文件 alter system checkpoint; 六、查这行数据所在的文件号和块号 SQL>col name for a10 SQL>select id,name,dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block# from t1; ID NAME FILE# BLOCK# ---------- --------- ---------- ---------- 1 AAAAA 6 135 七、转储6号文件135号块,新开个窗口 [oracle@guoyj ~]$ sqlplus / as sysdba SQL> alter system dump datafile 6 block 135; 八、找到转储的文件 SQL> show parameter dump NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ background_core_dump string partial background_dump_dest string /u01/app/oracle/diag/rdbms/bxo cp/bxocp/trace 再开一新窗口 [oracle@guoyj ~]$ cd /u01/app/oracle/diag/rdbms/bxocp/bxocp/trace [oracle@guoyj trace]$ ls -lFtr 下面这个跟踪日志就是6号文件135号块转储出来的数据块信息 -rw-r----- 1 oracle oinstall 3363 Dec 11 18:02 bxocp_ora_5429.trc - 九、分析数据块结构 [oracle@guoyj trace]$ vi bxocp_ora_5429.trc Trace file /u01/app/oracle/diag/rdbms/bxocp/bxocp/trace/bxocp_ora_5429.trc Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options ORACLE_HOME = /u01/app/oracle/product/11.2.0 System name: Linux Node name: guoyj Release: 2.6.18-128.el5 Version: #1 SMP Wed Dec 17 11:41:38 EST 2008 Machine: x86_64 VM name: VMWare Version: 6 Instance name: bxocp Redo thread mounted by this instance: 1 Oracle process number: 28 Unix process pid: 5429, image: oracle@guoyj (TNS V1-V3) *** 2012-12-11 18:02:31.307 *** SESSION ID:(29.15) 2012-12-11 18:02:31.307 *** CLIENT ID:() 2012-12-11 18:02:31.307 *** SERVICE NAME:(SYS$USERS) 2012-12-11 18:02:31.307 *** MODULE NAME:(sqlplus@guoyj (TNS V1-V3)) 2012-12-11 18:02:31.307 *** ACTION NAME:() 2012-12-11 18:02:31.307 Start dump data blocks tsn: 7 file#:6 minblk 135 maxblk 135 Block dump from cache: Dump of buffer cache at level 4 for tsn=7 rdba=25165959 BH (0x7f3f6958) file#: 6 rdba: 0x01800087 (6/135) class: 1 ba: 0x7f33a000 set: 3 pool: 3 bsz: 8192 bsi: 0 sflg: 1 pwc: 103,28 dbwrid: 0 obj: 76987 objn: 76987 tsn: 7 afn: 6 hint: f hash: [0x908b5100,0x908b5100] lru: [0x7f3f6910,0x7f3f6b70] ckptq: [NULL] fileq: [NULL] objq: [0x7f3f6938,0x8d148e00] objaq: [0x7f3f6948,0x8d148df0] st: XCURRENT md: NULL fpin: 'ktspbwh2: ktspfmdb' tch: 3 flags: block_written_once redo_since_read LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN: [0xffff.ffffffff] HSUB: [1] Block dump from disk: buffer tsn: 7 rdba: 0x01800087 (6/135) scn: 0x0000.0015a3eb seq: 0x01 flg: 0x06 tail: 0xa3eb0601frmt: 0x02 chkval: 0xec19 type: 0x06=trans data
|
Hex dump of block: st=0, typ_found=1 Dump of memory from 0x00002B70E9566A00 to 0x00002B70E9568A00 2B70E9566A00 0000A206 01800087 0015A3EB 06010000 [................] 2B70E9566A10 0000EC19 00000001 00012CBB 0015A3EA [.........,......] 2B70E9566A20 00000000 0032F802 01800080 000F0004 [......2.........] 2B70E9566A30 00000346 00C00793 002200BB 00002001 [F.........".. ..] 2B70E9566A40 0015A3EB 00000000 00000000 00000000 [................] 2B70E9566A50 00000000 00000000 00000000 00000000 [................] 2B70E9566A60 00000000 00010100 0014FFFF 1F781F8C [..............x.] 2B70E9566A70 00001F78 1F8C0001 00000000 00000000 [x...............] 2B70E9566A80 00000000 00000000 00000000 00000000 [................] Repeat 502 times 2B70E95689F0 0202012C 410502C1 41414141 A3EB0601 [,......AAAAA....] 1.数据块头 Block header dump: 0x01800087 Object id on Block? Y seg/obj: 0x12cbb csc: 0x00.15a3ea itc: 2 flg: E typ: 1 - DATA brn: 0 bdba: 0x1800080 ver: 0x01 opc: 0 inc: 0 exflg: 0
|
seg/obj: 0x12cbb --16进制转成10进制76987 SQL> select object_id from dba_objects where object_name='T1' and owner='GYJ'; OBJECT_ID ---------- 76987 csc: 0x00.15a3ea --cleanoutSCN,块清除时的SCN itc: 2 --指向第二个事务槽 flg: E --指用的是ASSM,如果是O表示用的是free list typ: 1 - DATA --类型是数据 2.事务槽 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0004.00f.00000346 0x00c00793.00bb.22 --U- 1 fsc 0x0000.0015a3eb 0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
|
Itl: ITL事务槽号的流水编号 Xid:transac[X]tion identified(事务ID),由und的段号+undo的槽号+undo槽号的覆盖次数三部分组成 Uba:undo block address记录了最近一次的该记录的前镜像(修改前的值) Flag:C是提交,U是快速提交,---是未提交 Lck:锁住了几行数据,对应有几个行锁 Scn/Fsc:Scn=SCN of commited TX; Fsc=Free space credit(bytes) 这里fsc 0x0000.0015a3eb是指提交的scn,这个值大于上次清除块时的scn=csc: 0x00.15a3ea(此scn是这个块中最小的SCN of commited) 3.用户数据头 bdba: 0x01800087 data_block_dump,data header at 0x2b70e9566a64 =============== tsiz: 0x1f98 hsiz: 0x14 pbl: 0x2b70e9566a64 76543210 flag=-------- ntab=1 nrow=1 frre=-1 fsbo=0x14 fseo=0x1f8c avsp=0x1f78 tosp=0x1f78 0xe:pti[0] nrow=1 offs=0 0x12:pri[0] offs=0x1f8c
|
bdba: 0x01800087 -- 数据块的地址:16进制转成2进制取前10位二进制为文件号0000 0001 1000 ..... 0000000110=5号文件,后面剩于的部分表示块号,0X87转成10进制为135号块 tsiz: 0x1f98 --top of size 块的总大小即8088个字节 hsiz: 0x14 --Data header size 数据头大小即20个字节 pbl: 0x2b70e9566a64 --Pointer to buffer holding the block 76543210 flag=-------- N=pcrfree hit(clusters);F=do not put on free list;K=flushable cluster keys ntab=1 --表示这个块的数据在一个表(如果是聚簇表就有可能是2或2以上) nrow=1 --表示这个表有一行数据 frre=-1 -- The first free row entry in the row directory=you have to add one fsbo=0x14 -- Free space begin offset可以存放数据空间的起始位置 fseo=0x1f8c -- Free space end offset可以存放数据空间的结束位置 avsp=0x1f78 --Available space for new entries tosp=0x1f78 --Total space 0xe:pti[0] nrow=1 offs=0 --Table directory,整个表的开始,共一行数据 0x12:pri[0] offs=0x1f8c --Row index,行的开始,第一行的位置 4.用户数据 block_row_dump: tab 0, row 0, @0x1f8c tl: 12 fb: --H-FL-- lb: 0x1 cc: 2 col 0: [ 2] c1 02 col 1: [ 5] 41 41 41 41 41 end_of_block_dump End dump data blocks tsn: 7 file#: 6 minblk 135 maxblk 135
|
tab 0, row 0, @0x1f8c --第一个表第一行的位置 tl: 12 fb: --H-FL-- lb: 0x1 cc: 2 --行头,tl: 12行长度12个字节, fb: (Flag byte)--H-FL指H(Head piece of row)F(First data piece) L(Last data piece) lb: 0x1 --Lock byte和上面的ITL的lck相对应,表示这行是否被lock了 cc: 2 --表示有两列,即这个表有两个字段 col 0: [ 2] c1 02 --第一行的第一个字段长度和值 col 1: [ 5] 41 41 41 41 41 --第一行的第二个字段长度和值 把字符转成16进制 SQL> select * from t1; ID NAME ------ ---- ----- 1 AAAAA SQL> select dump(01,'16') from dual; DUMP(01,'16') ----------------- Typ=2 Len=2: c1,2 SQL> select dump('AAAAA','16') from dual; DUMP('AAAAA','16') ---------------------------- Typ=96 Len=5: 41,41,41,41,41 反过来把16进制转成字符 SQL> select chr(to_number(substr(replace('41 41 41 41 41',' '),2*rownum-1,2),'xxxxxxxx')) from dba_objects where rownum<=5; CH -- A A A A A 不过对数值类型的不能这样转化,要写过比较复杂的过程把各种字符都考虑进去。。。 数据块的最后四字节tail: 0xa3eb0601=scnBASE+flg+seq,如果不相等会报块损坏!!! scn: 0x0000.0015a3eb seq: 0x01 flg: 0x06 |