ORACLE ROWID的一点知识

来源:互联网 发布:linux 编译器 编辑:程序博客网 时间:2024/05/17 08:23

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。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 工作中老是粗心不细心怎么办 小孩数学总是特别粗心该怎么办 孩子起范疙瘩的怎么办 做题马虎不认真怎么办 孩子考差了家长怎么办 小孩写作业不认真怎么办 小孩不认真检查作业怎么办 一年级的小孩作业不认真怎么办 一年级学生做题粗心怎么办 一年级的学生做题粗心怎么办 孩子做作业注意力不集中怎么办 小学三年孩子抄答案怎么办 孩子写作业不认真审题怎么办 一年级小孩审题不认真怎么办 孩子审题不认真马虎怎么办 孩子做作业不认真审题怎么办? 考老师考砸了怎么办 重要考试考砸了怎么办 二年级孩子做数学题粗心怎么办 二年级孩子考试粗心怎么办 二年级孩子考试总是粗心怎么办 二年级孩子总是粗心怎么办 小学一年级孩子抄别人作业怎么办 被老师发现抄答案怎么办 考试抄答案被老师发现怎么办 孩子撒谎不写作业怎么办 小学生做题容易马虎出错怎么办 小学生做题老是马虎怎么办 小学生做题马虎不认真怎么办 会做的题总做错怎么办 孩子数学做题粗心怎么办 孩子成绩考差了怎么办 孩子静不下心学习怎么办 孩子考试时总是粗心马虎怎么办 小学二年级学生厌学怎么办 三岁宝宝肚脐痛怎么办 做题速度太慢怎么办 孩子做题不动脑不会转弯怎么办? 孩子做题总是马虎怎么办 孩子做题总是眼高手低怎么办 小孩说幼儿园老师不喜欢他怎么办