ORACLE ROWID的一點知識

oracle8的ROWID結構
2004-04-23 15:18 pm

來自:Linux文檔
地址:http://linux.sheup.com/linux/linux3983.htm

1、爲什麼使用ROWID
ORACLE把ROWID作爲B-樹和其內部算法標示ROW的唯一標示。
在ORACLE8以前的版本中,ROWID標示FILE、BLOCK、ROW NUMBER,只用一個數字代
表FILE號。
在ORACLE8中,一個DATAFILE有兩個數字代表:
一個絕對值,是整個數據庫唯一的。可以看DBA_DATA_FILES中的FILE_ID。
一個相對值,在TABLESPACE中是唯一的,可以看DBA_DATA_FILES中的RELATIVE_
FNO。

新的ROWID使用相對值,所以必須存放SEGMENT的標示,否則就會混淆。所以ORAC
LE8在ROWID中加入對象的SEGMENT號,用來標示TABLE或者PARTITION。

2、ROWID的結構
使用base-64代碼,包括a-z,A-Z,0-9,+,-。一共18位。
1-6位:代表OBJECT
7-9位:文件相對值
10-15:文件中的BLOCK
16-18:BLOCK中的SLOT值

3、TABLESPACE-Relative尋址方式
使用的是TABLESPACE-Relative尋址方式,多個文件可以有相同的相對值,因爲它
們屬於不同的TABLESPACE,所以不能從新的ROWID得到絕對地址,但是這沒有問題
,因爲當要處理某個OBJECT時,已經能確定它屬於哪個TABLESAPCE了。在TABLES
PACE中,文件相對值是唯一的,所以ROWID還是可以唯一標示一個OBJECT。TABLE
SPACE-Relative尋址方式是ORACLE8中支持超大數據庫的關鍵技術。

4、DATA OBJECT NUMBER
DATA OBJECT NUMBER用於指示SEGMENT,所有SEGMENT都有DATA OBJECT NUMBER,
存放在每個DATA BLOCK中,而且不重複。

最開始的時候,DBA_OBJECTS.OBJECT_ID=DBA_OBJECTS.DATA-OBJECT_ID,但是在
上述情況下DATA-OBJECT_ID會在如下情況下增加
TRUNCATE TABLE
MOVE PARTITION
ORACLE會檢查ROWID中的DATA OBJECT NUMBER和BLOCK中的DATA OBJECT NUMBER,
保證他們之間的版本是一致的。
ORACLE也使用DATA OBJECT NUMBER以確保ROLLBACK的紀錄和最新的SEGMENT紀錄一
致。
要注意的是DATA OBJECT NUMBER不是OBJECT 的標誌


5、RESTRICTED ROWID
ORACLE7的ROWID格式是
1-8位:BLOCK NUMBER
9-12位:ROW NUMBER
13-16位:FILE NUMBER
ORACLE8支持短的、舊格式的ROWID,作用是
對NOPARTITION TABLE的INDEX ENTRY
對PARTITION TABLE的LOCAL INDEX ENTRY
ROW Piece CHain pointer
受限ROWID的內部存放是6BYTE,
4BYTE=DATA BLOCK NUMBER
2BYTE=ROW NUMBER
這就是說,INDEX ENTRY使用6BYTE存放該ROWID,這對大多數INDEX足夠了。但是
這種短ROWID不能使用在PATITION TABLE的GLOBAL INDEX上,因爲PARTITION可能
跨TABLESPACE。顯示這種ROWID依然是18位的

6、擴展的ROWID
ORACLE在內部存放時候是10 BYTE,包括(DATA OBJECT NUMBER,DATA BLOCK NU
MBER,ROW NUMBER)
ORACLE8使用擴展的ROWID:
PARTITION TABLE 的GLOBAL INDEX
SERVER 算法
擴展的ROWID在SELECT時,依然是18位的顯示,存放在ROWID字段中。

7、在ORACLE8中使用ORACLE7的ROWID
從ORACLE8的DB中查詢ORACLE7的ROWID時候,ROWID返回的是ORACLE7的格式,也可
以用在WHERE語句中。
從ORACLE7的DB中查詢ORACLE8的ROWID時候,ROWID返回的是ORACLE8的格式,也可
以用在WHERE語句中,但是不能存放在ROWID字段中。但是你要用DBMS_ROWID 包來
解釋之。
如果包含擴展的ORACLE8 ROWID,這不能把ORACLE8的數據IMPORT到ORACLE7中。從
ORACLE7中可以IMPORT到ORACLE8中。

8、APPLICATION的移植問題
一般程序的移植應該沒有問題。只有在下面情況下才考慮移植問題:
application使用了rowid
table包括ROWID類型的字段
如果程序有如下情況,必須使用DBMS_ROWID包:
自己組合ROWID
自己分解ROWID
如果僅僅是傳遞ROWID到變量、或者僅僅做爲一個整體使用,則可以不受影響。


9、數據的移植問題
無論使用EXPORT/IMPORT還使用移植工具,ORACLE7中的ROWID字段到了ORACLE8中
就自動擴展。
如果在某個字段內容中包含ROWID,則必須手工用DBMS_ROWID包來轉換。

10、DBMS_ROWID包
由$ORACLE_HOME/rdbms/admin/dbmsutil.sql創建,其實在catproc.sql中包含着
。提供處理ROWID的一些函數。
ROWID_CREATE
ROWID_INFO
ROWID_TYPE
ROWID_OBJECT
ROWID_RELATIVE_FNO
ROWID_BLOCK_NUMBER
ROWID_TO_ABSOLUTE_FNO
ROWID_TO_EXTENDED
ROWID_TO_RESTRICTED
ROWID_VERIFY

 

DBMS_ROWID.ROWID_TO_EXTENDED
(old_rowid in ROWID,
schema_name in varchar2,
object_name in varchar2,
conversion_type in number
)
RETURN ROWID;
轉換受限rowid到擴展rowid,用於轉換舊的ROWID到ORACLE8的格式。


DBMS_ROWID.ROWID_TO_RESTRICTED
轉換擴展的ROWID到受限的ROWID。

DBMS_ROWID.ROWID_VERIFY
判斷一個受限的ROWID是否可以轉換到擴展的格式


DBMS_ROWID.ROW_INFO
用於解釋ROWID,可以得到DATA OBJECT NUMBER,RELATIVE FILE NUMBER,BLOCK
NUMBER和ROW NUMBER。

DBMS_ROWID.CREATE
生成ROWID。

結束

 


 

 

oracle ROWID結構分析

 

引自:http://rainnyzhong.bokee.com/5793871.html

                                      
Oracle的文檔上沒有介紹邏輯ROWID的編碼規則,而且通過DUMP的結果也很難反推出編碼規則。因此,本文只簡單討論一下邏輯ROWID的存儲。

下面來看例子。

 


SQL> create table test_index (id number primary key, name varchar2(20)) organization index;

表已創建。

SQL> insert into test_index values (1, 'a');

已創建 1 行。

SQL> commit;

提交完成。

SQL> col dump_rowid format a60
SQL> select rowid, dump(rowid) dump_rowid from test_index;

ROWID                       DUMP_ROWID
--------------------------- ----------------------------------------
*BAFAB4wCwQL+               Typ=208 Len=10: 2,4,1,64,7,140,2,193,2,254

邏輯ROWID的DUMP結果前兩位都是2和4,最後一位都是254,(我還沒有發現其他的情況),由於邏輯ROWID和主鍵的值有關,所以長度是不定的,因此應該是用來表示開始和結束的。

第3、4位和物理ROWID一樣,表示的是相對錶空間的數據文件號乘以64的值。

第5、6位表示這條記錄在數據文件的第幾個BLOCK中。

從第7位開始到DUMP結果的倒數第二位,表示主鍵的值。首先是主鍵中第一個字段的長度,這裏是2,然後是主鍵的值,由於是NUMBER類型,因此193,2表示數值1。如果是多個字段組成的主鍵,第一個字段之後是第二個字段的長度,然後是第二個字段的值……。

SQL> select (1*256 + 64)/64 from dual;

(1*256+64)/64
-------------
            5

SQL> select 7*256 + 140 from dual;

 7*256+140
----------
      1932

SQL> alter system dump datafile 5 block 1932;

系統已更改。

找到相應的dump文件,可以發現剛纔插入的記錄。

Dump file f:oracleadmintest4udumptest4_ora_3828.trc
Thu Dec 23 00:17:53 2004
ORACLE V9.2.0.4.0 - Production vsnsta=0
vsnsql=12 vsnxtr=3
Windows 2000 Version 5.1 Service Pack 1, CPU type 586
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
Windows 2000 Version 5.1 Service Pack 1, CPU type 586
Instance name: test4

Redo thread mounted by this instance: 1

Oracle process number: 9

Windows thread id: 3828, image: ORACLE.EXE


*** 2004-12-23 00:17:53.361
*** SESSION ID:(8.82) 2004-12-23 00:17:53.301
Start dump data blocks tsn: 5 file#: 5 minblk 1932 maxblk 1932
buffer tsn: 5 rdba: 0x0140078c (5/1932)
scn: 0x0000.00e9f122 seq: 0x01 flg: 0x02 tail: 0xf1220601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump:  0x0140078c
 Object id on Block? Y
 seg/obj: 0x1e48  csc: 0x00.e9f113  itc: 2  flg: E  typ: 2 - INDEX
     brn: 0  bdba: 0x1400789 ver: 0x01
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x02   0x0005.008.000000e7  0x00800226.005c.24  --U-    1  fsc 0x0000.00e9f122
 
Leaf block dump
===============
header address 71963236=0x44a1264
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x90: opcode=0: iot flags=I-- is converted=Y
kdxconco 1
kdxcosdc 0
kdxconro 1
kdxcofbo 38=0x26
kdxcofeo 8026=0x1f5a
kdxcoavs 7988
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[8026] flag: K----, lock: 2
col 0; len 2; (2):  c1 02
tl: 5 fb: --H-FL-- lb: 0x0  cc: 1
col  0: [ 1]
Dump of memory from 0x044A31C7 to 0x044A31C8
44A31C0          61010100                        [...a]       
----- end of leaf block dump -----
End dump data blocks tsn: 5 file#: 5 minblk 1932 maxblk 1932

可以看到,根據DUMP結果的3、4、5、6位可以定位記錄的物理位置。

需要注意的是,索引組織表以主鍵的順序存儲數據,因此插入、更新和刪除數據都可能造成一條記錄的物理位置發生變化,這時通過ROWID 中的DATAFILE和BLOCK的信息可能就無法正確定位到記錄的物理位置。當根據邏輯ROWID訪問索引組織表時,首先會根據DATAFILE和 BLOCK信息去找到相應的BLOCK,檢查數據是否在這個BLOCK中,如果不在,就通過邏輯ROWID中的主鍵信息去通過索引掃描,找到這條記錄。這就是Oracle文檔在提到的physical guess。

下面看一個由字符串和日期組成聯合主鍵的例子。

SQL> create table test_index2 (id char(4), time date,
  2  constraint pk_test_index2 primary key (id, time)) organization index;

表已創建。

SQL> insert into test_index2 values ('1', sysdate);

已創建 1 行。

SQL> col dump_rowid format a75
SQL> select rowid, dump(rowid) dump_rowid from test_index2;

ROWID                        DUMP_ROWID
---------------------------- ------------------------------------------------------------------
*BAFAB5QEMSAgIAd4aAwXASMT/g  Typ=208 Len=20: 2,4,1,64,7,148,4,49,32,32,32,7,120,104,12,23,1,35,19,254

可以看出,第7位是字段id的長度4,然後是字符串1和三個空格的ASCII碼,這是字符串的存儲格式,後面跟着的7是字段time長度,後面七位是日期的存儲格式。在邏輯ROWID中,數值、字符和日期類型的存儲格式都和它們本身的存儲格式一致,這裏不在贅述。

 

一般情況下,使用一位來表示長度,但是如果長度超過了127(16進制DUMP的結果是7F),則長度開始用兩位表示。第一位以8開頭,這個8只是標識位,表明長度字段現在由兩位來表示。例如長度128表示位8080,而支持的最大值3800表示爲8ED8。

 

本文來自CSDN博客,轉載請標明出處:file:///D:/my%20documents/oracle/ORACLE%20ROWID的一點知識%20-%20FALENT的專欄%20-%20CSDN博客.mht

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章