说说Oracle的rowid
发布时间:2010/6/29 14:39:41 来源:城市学习网 编辑:ziteng
在Oracle中rowid唯一标识每条记录所在的位置,它作为一个伪列在查询中出现:
1 select rowid,id
2 from test_table
3 where rownum<=10 ;
01 ROWID ID
02 ------------------ ----------
03 AAAVcbAAPAAAAALAAA 1
04 AAAVcbAAPAAAAALAAB 2
05 AAAVcbAAPAAAAALAAC 3
06 AAAVcbAAPAAAAALAAD 4
07 AAAVcbAAPAAAAALAAE 5
08 AAAVcbAAPAAAAALAAF 6
09 AAAVcbAAPAAAAALAAG 7
10 AAAVcbAAPAAAAALAAH 8
11 AAAVcbAAPAAAAALAAI 9
12 AAAVcbAAPAAAAALAAJ 10
rowid是由18个字符组成分4个部分,分别是:
6个字符的对象编号,3个字符的文件号,6个字符的块编号,3个字符的行编号。
每一个字符的取值范围以及对应的数值是:
01 --------------------------------
02 | A| 0| | a| 26| | 0| 52|
03 | B| 1| | b| 27| | 1| 53|
04 | C| 2| | c| 28| | 2| 54|
05 | D| 3| | d| 29| | 3| 55|
06 | E| 4| | e| 30| | 4| 56|
07 | F| 5| | f| 31| | 5| 57|
08 | G| 6| | g| 32| | 6| 58|
09 | H| 7| | h| 33| | 7| 59|
10 | I| 8| | i| 34| | 8| 60|
11 | J| 9| | j| 35| | 9| 61|
12 | K| 10| | k| 36| | +| 62|
13 | L| 11| | l| 37| | /| 63|
14 | M| 12| | m| 38| | | |
15 | N| 13| | n| 39| | | |
16 | O| 14| | o| 40| | | |
17 | P| 15| | p| 41| | | |
18 | Q| 16| | q| 42| | | |
19 | R| 17| | r| 43| | | |
20 | S| 18| | s| 44| | | |
21 | T| 19| | t| 45| | | |
22 | U| 20| | u| 46| | | |
23 | V| 21| | v| 47| | | |
24 | W| 22| | w| 48| | | |
25 | X| 23| | x| 49| | | |
26 | Y| 24| | y| 50| | | |
27 | Z| 25| | z| 51| | | |
28 --------------------------------
可以看到rowid是一个64进制的表示方式,利用上述对应表即可计算出:
对象编号:AAAVcb = 87835
文件号:AAP = 41
块号:AAAAAL =11
行号:AAA~AAJ = 0 ~ 9
16进制的转换完全可以交给机器去做,Oracle也是这么认为的,于是提供了一个叫做dbms_rowid的包,它包含了一系列的方法,我们借助这个包就可完成上述的工作了:
1 select rowid ,
2 substr(rowid,1,6) ||' : '|| dbms_rowid.rowid_object(rowid) "数据对象编号/object_id",
3 substr(rowid,7,3) ||' : '|| dbms_rowid.rowid_relative_fno(rowid) "文件编号/file_id",
4 substr(rowid,10,6)||' : '|| dbms_rowid.rowid_block_number(rowid) "块编号/block_id",
5 substr(rowid,16,3)||' : '|| dbms_rowid.ROWID_ROW_NUMBER(rowid) "行编号/row_num"
6 from test_table
7 where rownum<=10;
01 ROWID 数据对象编号/object_id 文件编号/file_id 块编号/block_id 行编号/row_num
02 ------------------ ------------------------- -------------------- -------------------- ---------------
03 AAAVcbAAPAAAAALAAA AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAA : 0
04 AAAVcbAAPAAAAALAAB AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAB : 1
05 AAAVcbAAPAAAAALAAC AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAC : 2
06 AAAVcbAAPAAAAALAAD AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAD : 3
07 AAAVcbAAPAAAAALAAE AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAE : 4
08 AAAVcbAAPAAAAALAAF AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAF : 5
09 AAAVcbAAPAAAAALAAG AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAG : 6
10 AAAVcbAAPAAAAALAAH AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAH : 7
11 AAAVcbAAPAAAAALAAI AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAI : 8
12 AAAVcbAAPAAAAALAAJ AAAVcb : 87835 AAP : 15 AAAAAL : 11 AAJ : 9 [NextPage] 这个结果对不对呢?我们可以这样验证,注意,以下查询需要DBA权限。
首先是object_id:
1 select
2 owner,object_name,object_id
3 from dba_objects
4 where object_name='TEST_TABLE';
1 OWNER OBJECT_NAME OBJECT_ID
2 ---------- -------------------- ----------
3 TEST TEST_TABLE 8783
然后是文件编号和块编号:
1 select
2 owner,segment_name,segment_type,extent_id,
3 file_id,block_id,blocks,bytes
4 from dba_extents
5 where segment_name='TEST_TABLE';
1 OWNER SEGMENT_NAME SEGMENT_TYPE EXTENT_ID FILE_ID BLOCK_ID BLOCKS BYTES
2 ------ ------------- ------------- ---------- -------- --------- ------- ------
3 TEST TEST_TABLE TABLE 0 15 8 8 65536
4 TEST TEST_TABLE TABLE 1 15 16 8 65536
编号为11的块落在了编号为0的exntent上,只能说是验证了一半,接下来我们将数据块dump出来看看,不过做之前先为这一行打上“标记”,看以下过程:
01 test$logdw@logdw SQL> select rowid,t.* from test_table t where rownum<=5;
02
03 ROWID ID DATA
04 ------------------ ---------- ------------------------------
05 AAAVcbAAPAAAAALAAA 1 Q
06 AAAVcbAAPAAAAALAAB 2 Q
07 AAAVcbAAPAAAAALAAC 3 Q
08 AAAVcbAAPAAAAALAAD 4 Q
09 AAAVcbAAPAAAAALAAE 5 Q
10
11 5 rows selected.
12 test$logdw@logdw SQL> update test_table set data=lpad('killkill',30) where id=1;
13
14 1 row updated.
15 test$logdw@logdw SQL> select rowid,t.* from test_table t where rownum<=5;
16
17 ROWID ID DATA
18 ------------------ ---------- ------------------------------
19 AAAVcbAAPAAAAALAAA 1 killkill
20 AAAVcbAAPAAAAALAAB 2 Q
21 AAAVcbAAPAAAAALAAC 3 Q
22 AAAVcbAAPAAAAALAAD 4 Q
23 AAAVcbAAPAAAAALAAE 5 Q
24
25 5 rows selected.
26 test$logdw@logdw SQL> commit;
做好了“标记”,可以dump数据块了:
1 sys$logdw@logdw SQL> select get_trace_name() from dual ;
2
3 GET_TRACE_NAME()
4 -----------------------------------------------------------------
5 /u01/app/oracle/diag/rdbms/logdw/logdw/trace/logdw_ora_29284.trc
6
7 sys$logdw@logdw SQL> alter system dump datafile 15 block 11 ;
8
9 System altered.
打开trc文件,摘录如下:
01 Start dump data blocks tsn: 10 file#:15 minblk 11 maxblk 11
02 ......
03 ......
04 Dump of memory from 0x0000002A96F31A00 to 0x0000002A96F33A00
05 ......
06 ......
07 2A96F31F20 20202020 20202020 20202020 6C696B20 [ kil]
08 2A96F31F30 6C696B6C 02002C6C 1E03C102 20202020 [lkill,...... ]
09 ......
10 ......
11 block_row_dump:
12 tab 0, row 0, @0x4ac
13 tl: 37 fb: --H-FL-- lb: 0x2 cc: 2
14 col 0: [ 2] c1 02
15 col 1: [30]
16 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6b 69 6c
17 6c 6b 69 6c 6c
18 ......
19 ......
你找到killkill了吗?