Extended Rowids
Extended rowids use a base 64 encoding of the physical address for each row
selected. The encoding characters are A-Z, a-z, 0-9, +, and /. For
example, the following query:
SELECT ROWID, last_name FROM employees WHERE department_id = 20;
can return the following row information:
ROWID LAST_NAME
------------------ ----------
AAAAaoAATAAABrXAAA BORTINS
AAAAaoAATAAABrXAAE RUGGLES
AAAAaoAATAAABrXAAG CHEN
AAAAaoAATAAABrXAAN BLUMBERG
An extended rowid has a four-piece format, OOOOOOFFFBBBBBBRRR:
_ OOOOOO: The data object number that identifies the database segment
(AAAAao in the example). Schema objects in the same segment, such as a cluster
of tables, have the same data object number.(数据对象号)
_ FFF: The tablespace-relative datafile number of the datafile that contains the
row (file AAT in the example).(关联的数据文件的ID)
_ BBBBBB: The data block that contains the row (block AAABrX in the
example). Block numbers are relative to their datafile, not tablespace. Therefore,
two rows with identical block numbers could reside in two different datafiles of
the same tablespace.(相应的数据块号)
_ RRR: The row in the block.(行号)
You can also use the DBMS_ROWID package to extract information from an extended
rowid or to convert a rowid from extended format to restricted format (or viceversa).
(这里我们也可以使用系统自带的DBMS_ROWID这个包来显示ROWID的相关信息及进行相应创建ROWID或转换)对这个包进行了追查,这里有叶梁老师的一篇介绍挺详细的:
http://blog.itpub.net/post/3/7835
DBMS_ROWID包的使用
DBMS_ROWID是一个比较有用的系统自带的package,主要可以用来处理坏块的问题,于是仔细的研究了一下,这个包可以用来了解file、block、object id和rowid之间的关系,在Oracle8中被引用进来,Oracle7不支持这个包。这个包的定义可以在dbmsutil.sql中找到,在catproc.sql中被调用,并被给予public执行权限。
首先来了解一下这个包中使用的常量:
ROWID类型: rowid_type_restricted RESTRICTED - Restricted ROWID(Oracle8 后就没有这种类型了)
rowid_type_extended EXTENDED - Extended ROWID
ROWID验证结果:
rowid_is_valid VALID - Valid ROWID
rowid_is_invalid INVALID - Invalid ROWID
目标类型:
rowid_object_undefined UNDEFINED - Object Number not defined (for restricted ROWIDs)
ROWID转换类型:
rowid_convert_internal INTERNAL - convert to/from column of ROWID type
rowid_convert_external EXTERNAL - convert to/from string format
意外错误:
ROWID_INVALID invalid rowid format
ROWID_BAD_BLOCK block is beyond end of file
在DBMS_ROWID这个包里面可以使用下面的功能:
function ROWID_CREATE(rowid_type IN number,
object_number IN number,
relative_fno IN number,
block_number IN number,
row_number IN number)
return ROWID;
-- rowid_type - 类型(restricted=0/extended=1)
-- object_number - 对象号
-- relative_fno - relative file number
-- block_number - 文件包含的block号
-- row_number - block中的行的行号
下面具体的讨论一下DBMS_ROWID包的用法:
1. DBMS_ROWID.ROWID_BLOCK_NUMBER:返回一个rowid的block号
定义如下:
function dbms_rowid.rowid_block_number
(row_id in rowid)
return number
SQL> select dbms_rowid.rowid_block_number(rowid) "block" from test; //这里的参数就是rowid后面可以跟上where限制条件
block
----------
23722
2. DBMS_ROWID.ROWID_CREATE:创建并返回一个基于单独行的rowid,创建的rowid类型是RESTRICTED或者是EXTENDED,这种功能一般都是用于测试目的,因为只有oracle才能创建一个合法的rowid指向数据。
定义如下:
function dbms_rowid.rowid_create
(rowid_type in number
,object_number in number
,relative_fno in number
,block_number in number
,row_number in number)
return rowid
例子:
创建一个restricted rowid:
SQL> select dbms_rowid.rowid_create(0, 6877,1,23722,0) from dual;
DBMS_ROWID.ROWID_C
------------------
00005CAA.0000.0001
创建一个extended rowid:
SQL> select dbms_rowid.rowid_create(1, 6877,1,23722,0) from dual;
DBMS_ROWID.ROWID_C
------------------
AAABrdAABAAAFyqAAA
3. DBMS_ROWID.ROWID_INFO: 返回一个单独组件的一个指定的rowid,它只能用于PL/SQL,而不能用于sql语句中。
定义如下:
procedure dbms_rowid.rowid_info
(rowid_in in rowid
,rowid_type out number
,object_number out number
,relative_fno out number
,block_number out number
,row_number out number)
例子:
SQL> set serverout on
SQL> set echo on
SQL> declare
2 my_rowid rowid;
3 rowid_type number;
4 object_number number;
5 relative_fno number;
6 block_number number;
7 row_number number;
8 begin
9 my_rowid :=dbms_rowid.rowid_create(1, 6877,1,23722,0);
10 dbms_rowid.rowid_info(my_rowid, rowid_type, object_number,
11 relative_fno, block_number, row_number);
12 dbms_output.put_line('ROWID: ' || my_rowid);
13 dbms_output.put_line('Object#: ' || object_number);
14 dbms_output.put_line('RelFile#: ' || relative_fno);
15 dbms_output.put_line('Block#: ' || block_number);
16 dbms_output.put_line('Row#: ' || row_number);
17 end;
18 /
ROWID: AAABrdAABAAAFyqAAA
Object#: 6877
RelFile#: 1
Block#: 23722
Row#: 0
PL/SQL 过程已成功完成。
4.DBMS_ROWID.ROWID_OBJECT:返回一个rowid的对象号。如果是restricted 的rowid,则返回0。
定义如下:
function dbms_rowid.rowid_object
(row_id in rowid)
return number
例子:
SQL> select dbms_rowid.rowid_object(rowid) "OBJECT" from test;
OBJECT
----------
6877
SQL> select dbms_rowid.rowid_object(dbms_rowid.rowid_to_restricted(rowid,0)) " OBJECT " from test;
OBJECT
----------
0
5. DBMS_ROWID.ROWID_RELATIVE_FNO: 返回一个rowid的相对文件号。
定义如下:
function dbms_rowid.rowid_relative_fno
(row_id in rowid)
return number
例子:
SQL> select dbms_rowid.rowid_relative_fno(rowid) "relative fno" from test;
relative fno
------------
1
6. DBMS_ROWID.ROWID_ROW_NUMBER:返回一个rowid的行号。(从零开始)
定义如下:
function dbms_rowid.rowid_row_number
(row_id in rowid)
return number
例子:
SQL> select dbms_rowid.rowid_row_number(rowid) "row" from test;
row
----------
0
7. DBMS_ROWID.ROWID_TO_ABSOLUTE_FNO:返回一个rowid的完全文件号。
定义如下:
function dbms_rowid.rowid_to_absolute_fno
(rowid in rowid
,schema_name in varchar2
,object_name in varchar2)
return number
例子:
SQL> select dbms_rowid.rowid_to_absolute_fno (rowid, 'SYS', 'TEST') "absolute fno" from test;
absolute fno
------------
1
8. DBMS_ROWID.ROWID_TO_EXTENDED: 转换一个restricted rowid为一个extended rowid.如果原始的rowid存储在列中,转换的 就是internal类型;如果原始的rowid是以字符串形式存储的,那转换的就是external类型。
定义如下:
function dbms_rowid.rowid_to_extended
(old_rowid in rowid
,schema_name in varchar2
,object_name in varchar2
,conversion_type in integer)
return rowid
例子:
转换restricted internal rowid为extended格式
SQL>select dbms_rowid.rowid_to_extended (dbms_rowid.rowid_to_restricted(rowid,0),'SYS','TEST',0) "extended rowid" from test;
extended rowid
------------------
AAABrdAABAAAFyqAAA
转换restricted external rowid为extended格式
SQL> select dbms_rowid.rowid_to_extended ('00005CAA.0000.0001','SYS','TEST',1) from dual;
DBMS_ROWID.ROWID_T
------------------
AAABrdAABAAAFyqAAA
如果参数中的SCHEMA和OBJECT为null,则默认是当前的对象
SQL>select dbms_rowid.rowid_to_extended (dbms_rowid.rowid_to_restricted(rowid,0),null,null,0) "extended rowid" from test;
extended rowid
------------------
AAABrdAABAAAFyqAAA
9. DBMS_ROWID.ROWID_TO_RESTRICTED:转换一个exteneded的rowid为一个restricted的rowid,restricted的rowid格式为BBBBBBB.RRRR.FFFFF, BBBBBBB代表block,RRRR 代表在block中的行号,从0开始,FFFFF代表文件号。这个包可以使用rowid或者rowid转换类型(ROWID_CONVERT_INTERNAL (0)和ROWID_CONVERT_EXTERNAL (1))
定义如下:
function dbms_rowid.rowid_to_restricted
(old_rowid in rowid
,conversion_type in integer)
return rowed
例子:
SQL> select dbms_rowid.rowid_to_restricted(rowid, 1) "restricted rowid" from test;
restricted rowid
------------------
00005CAA.0000.0001
Block计算:5*16*16*16+C*16*16+A*16+A=20480+3072+160+10=23722
10.DBMS_ROWID.ROWID_TYPE:返回rowid的类型,ROWID_TYPE_RESTRICTED(0)和ROWID_TYPE_EXTENDED(1)。
定义如下:
function dbms_rowid.rowid_type
(row_id in rowid)
return number;
例子:
Oracle8以后的版本的rowid都是extended类型
SQL> select dbms_rowid.rowid_type(rowid) "type" from test;
type
----------
1
Oracle7的rowid是restricted类型
SQL> select dbms_rowid.rowid_type(chartorowid('00005CAA.0000.0001')) "type" from dual;
type
----------
0
11.DBMS_ROWID.ROWID_VERIFY:验证一个restricted的rowid是否能够转换成extended的rowid,它可以用来发现存在问题的rowid。
定义如下:
function rowid_verify(rowid_in IN rowid,
schema_name IN varchar2,
object_name IN varchar2,
conversion_type IN integer)
return number;
介绍了这个包的用法后,其实对于我们最主要的还是利用DBMS_ROWID.ROWID_CREATE来解决坏块的一些问题,下面举一个具体如何使用这个包来解决坏块的例子。