这一篇是关于ROWID的, 文中大部分知识来自于Internet, 自己研究的地方颇少, 讲的不明白的也可以参照网上相关资源.
前面我们在研究索引的时候, 知道ORACLE最终是通过ROWID来找到数据的具体位置的.
通常,我们在下SELECT语句查询一个TABLE的时候, 加上ROWID:
SELECT ROWID, a.* FROM apps.ZZ_TIM_TEST2 a |
就会看到以下的ROWID形式:
AABfJBAGMAAAJ5IAAA |
下面我们来解析一下这个ROWID, ROWID的结构如下:
data object number(6位字符串): AABfJB
relative file number(3位字符串): AGM
block number(6位字符串): AAAJ5I
row number(3位字符串): AAA
这18位ROWID采用的64进制, 规则如下:
分别用A~Z、a~z、0~9、+、/共64个字符表示。A表示0,B表示1,……Z表示25,a表示26,……z表示51,0表示52,……,9表示61,+表示62,/表示63.
所以OBJECT_ID = AABfJB = 0 0 1 31 9 1 = 1*64*64*64 + 31*64*64 + 9*64 + 1 = 389697
依次得出R_FILE_NO = 396
BLOCK_NO = 40520
ROW_NO = 0
其实以上过程, 可以通过DBMS_ROWID这个包的一些函数来实现:
rowid_object
rowid_relative_fno
rowid_block_number
rowid_row_number
于是, 我们得到了这条记录所在的data_file_id, block_number, 就可以dump出来这个block的数据进行查看了.
(我们这里得到的data_file_id是related_data_file_id, 可以通过
DBMS_ROWID. rowid_to_absolute_fno来得到实际的data_file_id)
有关这二者的关系, 可以查看网上相关资源.
ALTER SYSTEM dump DATAFILE 396 block 40520 |
我们这里看到的ROW是AABfJBAGMAAAJ5IAAA形式的, 但是我们在前面研究索引的时候, 看到每条索引中存储的ROWID确不是这个样子的:
row#0[8004] flag: -----, lock: 0 col 0; len 2; (2): c1 18 col 1; len 6; (6): 63 00 9e 48 00 00 |
其实这个ROWID只是包含了前面ROWID的后面3部分:
R_FILE_NO, BLOCK_NO, ROW_NO
并且也需要通过如下解析:
首先转换为2进制:
0110 0011 0000 0000 1001 1110 0100 1000 0000 0000
然后, 最右边8位 0000 0000表示ROW_NO = 0
接下来22位表示00 0000 1001 1110 0100 1000 表示BLOCK_NO = 40520
接下来10位 0110 0011 00表示 R_FILE_NO = 396.