您的位置:首页 > 数据库 > Oracle

转:关于oracle rowid 的含义。

2008-04-28 18:59 405 查看

ROWID的含义与块地址rdba深入分析

作者:piner (转载请注明本文出处:Ixdba.com)
永久链接:http://www.ixdba.com/html/y2007/m04/77-oracle-rowid-rdba.html
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的信息,文件信息,块信息与行信息等等,如根据其中块的信息,可以知道该表确切占用了多少个块,每行在哪个块上,哪个数据文件上。
用例子说明一下Rowid的组成:

SQL> select rowid from emp where rownum = 1;

AAAAeNAADAAAAWZAAA

分解一下,可以看到
Data Object number = AAAAeN
File               = AAD
Block              = AAAAWZ
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= AAAAeN为例子,
N是64进制中的13,位置为0
13 * (64 ^ 0) = 13
E是64进制中的30,位置为1
30 * (64 ^ 1) = 1920
A是64进制中的 0
所以
A * (64 ^ 2) = 0
A * (64 ^ 3) = 0
A * (64 ^ 4) = 0
A * (64 ^ 5) = 0

则有AAAAeN = 0 + 0 + 0 + 0 + 1920 + 13 = 1933,表示该行存在的对象,对应的对象号为1933。
而且,我们也可以利用oracle提供的包,dbms_rowid来做到这一点:

select dbms_rowid.rowid_object('AAAAeNAADAAAAWZAAA') data_object_id#,

dbms_rowid.rowid_relative_fno('AAAAeNAADAAAAWZAAA') rfile#,

dbms_rowid.rowid_block_number('AAAAeNAADAAAAWZAAA') block#,

dbms_rowid.rowid_row_number('AAAAeNAADAAAAWZAAA') row# from dual;

DATA_OBJECT_ID# RFILE# BLOCK# ROW#

--------------- ---------- ---------- ----------

1933 3 1433 0

关于更多dbms_rowid的用法,可以参考包的说明或者是oracle手册。

如果明白了以上ROWID的含义,那么我们就很容易理解块的地址了rdba了,也就是ROWID中的FFFBBBBBB部分,10bit rfile#+22bit,如我们分析一个块地址:
DBA: 0×2fc0100a
那么,把0×2fc0100a转换成2进制为
2    f    c    0    1     0   0    a
0010 1111 1100 0000 0001 0000 0000 1010
再次转换
0010 1111 11                00 0000 0001 0000 0000 1010
=——————                —————————
数据文件id                  块ID
=191(十进制)                =4106(十进制)

或者0×2fc0100a=十进制的801116170

SQL> select dbms_utility.data_block_address_file(801116170) "file",

2 dbms_utility.data_block_address_block(801116170) "block"

3 from dual;

file block

---------- ----------

191 4106

注意,这里得到的191是rfile#,相对文件号,而相对文件号是不能超过1023,所以,如果你想根据这个地址来dump数据文件块的话,最好还是核对一下v$datafile:
select file# from v$datafile where rfile# = 191 and ts# = <:dbfile_in_ts>


SQL> select file# from v$datafile where rfile# = 191 and ts# = 9;

FILE#

----------

1214

这里的9代表该数据文件所在的表空间的编号,你是不是惊奇的发现,这个块地址真正的数据文件编号应当是1214。而不是我们转换得到的191。
不过一般的情况下,数据库的数据文件都没有1023个,所以这个时候的数据文件编号file#与rfile#基本是对应的,这个时候,如果我们要dump这个数据块,就可以采用如下的方式来dump

alter system dump datafile 1214 block 4106;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: