当前位置:Gxlcms > mysql > Oracle的rowid和rdba庖丁解牛

Oracle的rowid和rdba庖丁解牛

时间:2021-07-01 10:21:17 帮助过:63人阅读

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# = <:dbfile_in_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-----

linux

人气教程排行