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