Oracle的rowid和rdba庖丁解牛 |
发布时间: 2012/8/15 17:47:32 |
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进制的,可以通过进制转化工具来查看(http://www.2u3.cn/Conversion/jinzhi/)
A-Z <==> 0 - 25 (26)
拿其中的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# 例如: 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----- 本文出自:亿恩科技【www.enkj.com】 |