在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了吗?