您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

Oracle的rowid和rdba庖丁解牛

2024/6/13 19:06:30发布46次查看
oracle 8以下rowid组成(也叫受限rowid)为:ffff.bbbbbbbb.rrrr,占用6个字节(10bit file#+22bit+16bit),但是,为了扩充的需
oracle 8以下rowid组成(也叫受限rowid)为:ffff.bbbbbbbb.rrrr,占用6个字节(10bit file#+22bit+16bit),但是,为了扩充的需要,如数据文件的扩充,现在的rowid改为:oooooofffbbbbbbrrr,占用10个字节(32bit+10bit rfile#+22bit+16bit)。其中,o是对象id,f是文件id,b是块id,r是行id。由于rowid的组成从file#变成了rfile#,所以数据文件数的限制也从整个库不能超过1023个变成了每个表空间不能超过1023个数据文件。
注意:这里的o,,代表的是data_object_id,是与段物理存储位置相关的一个信息,因为一个段对象只可能在一个表空间上,data_object_id能唯一确认ts#,而data_object_id + rfile#就能最终定位到该rowid在那个确定的物理数据文件。 
如果我们查询一个表的rowid,就可以获得object的信息,文件信息,块信息与行信息等等,如根据其中块的信息,可以知道该表确切占用了多少个块,每行在哪个块上,哪个数据文件上。 
我们在select数据时候,在不指定排序字段时, oracle是按rowid升序取数据的。如
sql> select t.id,rowid from skate.tab2 t;
        id rowid
---------- ------------------
   1067511 aaao1laaeaaahkkaaa
   1067513 aaao1laaeaaahkkaab
   1067515 aaao1laaeaaahkkaac
   1067517 aaao1laaeaaahkkaad
   1067519 aaao1laaeaaahkkaae
   1067523 aaao1laaeaaahkkaag
   1067525 aaao1laaeaaahkkaah
   1067527 aaao1laaeaaahkkaai
8 rows selected
sql> 
可以从上面的显示数据看到,是按rowid降序排列。我们拿rowid “aaao1laaeaaahkkaaa”来说明 
data object number =aaao1l
file id                  =aae    
block id              =aaahkk
row        =aaa
rowid是64进制的,可以通过进制转化工具来查看()
a-z 0 - 25 (26)
a-z 26 - 51 (26)
0-9 52 - 61 (10)
+/ 62 - 63 (2)
拿其中的data object number= aaao1l为例子,
l是64进制中的37,位置为0
37 * (64 ^ 0) = 37
1是64进制中的53,位置为1
53 * (64 ^ 1) = 3392
o是64进制中的 14,位置为2
14*(64^2)=57344
a是64进制中的 0
所以
a * (64 ^ 3) = 0
a * (64 ^ 4) = 0
a * (64 ^ 5) = 0
则有aaao1l= 0 + 0 + 0 + 57344+ 3392 + 37 = 60773,表示该行存在的对象,对应的对象号为60773。
手工算还是比较麻烦的,oracle为此提供相应的函数dbms_rowid来实现
sql> select dbms_rowid.rowid_object('aaao1laaeaaahkkaaa') data_object_id#,
  2         dbms_rowid.rowid_relative_fno('aaao1laaeaaahkkaaa') rfile#,
  3         dbms_rowid.rowid_block_number('aaao1laaeaaahkkaaa') block#,
  4         dbms_rowid.rowid_row_number('aaao1laaeaaahkkaaa') row# from dual;
data_object_id#     rfile#     block#       row#
--------------- ---------- ---------- ----------
          60773          4      29348          0
可以通过包的说明或者oracle官方手册了解更多,例如:
sql> desc dbms_rowid
element                type     
---------------------- ---------
rowid_type_restricted  constant 
rowid_type_extended    constant 
rowid_is_valid         constant 
rowid_is_invalid       constant 
rowid_object_undefined constant 
rowid_convert_internal constant 
rowid_convert_external constant 
rowid_invalid          exception
rowid_bad_block        exception
rowid_create           function 
rowid_info             procedure
rowid_type             function 
rowid_object           function 
rowid_relative_fno     function 
rowid_block_number     function 
rowid_row_number       function 
rowid_to_absolute_fno  function 
rowid_to_extended      function 
rowid_to_restricted    function 
rowid_verify           function
sql> desc dbms_rowid.rowid_info
parameter     type     mode default?
------------- -------- ---- --------
rowid_in      rowid    in           
rowid_type    number   out          
object_number number   out          
relative_fno  number   out          
block_number  number   out          
row_number    number   out          
ts_type_in    varchar2 in   y   
如果明白了以上rowid的含义,那么就很容易理解块的地址rdba了,也就是rowid中的fffbbbbbb部分,10bit rfile#+22bit,如我们分析一个块地址:
 rdba: 0x010072a4
把0x010072a4转化为10进制16806564
sql>   select dbms_utility.data_block_address_file(16806564) file,
  2           dbms_utility.data_block_address_block(16806564) block
  3    from dual;
file      block
---------- ----------
         4      29348
sql> 
现在通过块的dba知道了file和block,那怎样确认我们推到的正确呢? 这个块地址是dump文件的内容,我们可以去dump文件核对下
start dump data blocks tsn: 4 file#: 4 minblk 29348 maxblk 29348
buffer tsn: 4 rdba: 0x010072a4 (4/29348)
scn: 0x0000.00e66a1e seq: 0x02 flg: 0x06 tail: 0x6a1e0602
frmt: 0x02 chkval: 0x4590 type: 0x06=trans data
hex dump of block: st=0, typ_found=1 
结果我们推导的和dump的内容是一样的,不过这里得到的4是rfile#,相对文件号,而相对文件号是不能超过1023,所以,如果你想根据这个地址来dump数据文件块的话,最好还是核对一下v$datafile:
select file# from v$datafile where rfile# = 4 and ts# =  
表空间的ts#可以通过如下sql得到:
  select ta.tablespace_name, da.ts#
    from dba_tablespaces ta, dba_data_files df, v$datafile da
   where ta.tablespace_name = df.tablespace_name
     and da.name = df.file_name
 例如:
sql> select file# from v$datafile where rfile# = 4 and ts# = 4; 
    file#
----------
         4
sql>
如果数据文件数大于1023个,这里file# 就不是4了,应该是个绝对文件号了,这就是file#和rfile#的区别。如果dump数据块,要用绝对文件号的,例如:
alter system dump  datafile 4 block 29348; 
也可以通过dba_segments,如
sql>  select header_file,header_block from dba_segments where owner='skate' and segment_name='tab2'; 
header_file header_block
----------- ------------
          4        29347
这里段头占有一个block,后面存储的就是数据,所以存储数据的块,应该是29348 
-----end-----
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product