ROWID中rfile#是表空间内相对文件号而非全局FILE_ID,LOCAL INDEX因分区绑定表空间可用6字节ROWID,GLOBAL INDEX需10字节含data_object_id#以定位跨表空间段;大文件表空间省略rfile#,block#扩展至32位;MOVE/TRUNCATE等操作使data_object_id变更导致ROWID全部失效。
ROWID里rfile#不是数据库全局文件号,而是表空间内相对编号
oracle的rowid不存绝对文件号(file_id),而存的是rfile#(relative file number)——它只在所属表空间内唯一。同一个rfile#=1,在users表空间和system表空间里指向完全不同的物理文件。这是因为rowid设计目标是“定位到块”,而非“定位到数据库”。oracle必须先知道对象属于哪个表空间,才能把rfile#映射成实际数据文件路径。
local index为什么能用6字节ROWID,global index却必须用10字节
分区表上的LOCAL INDEX每个索引分区只对应一个表分区,而该表分区必然落在某个确定的表空间里。Oracle查索引时,已知当前索引分区归属的表空间,所以拿到rfile#后可直接换算出真实文件。但GLOBAL INDEX跨所有分区,索引条目可能指向任意表空间里的任意数据文件——没有data_object_id#就无法反推出它属于哪个段、进而无法确定rfile#对应的表空间上下文。所以GLOBAL INDEX必须存储完整的10字节扩展ROWID,其中data_object_id#用来查DBA_OBJECTS确认段归属,再结合rfile#完成定位。
大文件表空间(BIGFILE)下ROWID结构彻底省掉rfile#
大文件表空间强制只允许一个数据文件,rfile#失去意义,于是ROWID格式变为OOOOOOBBBBBBBBBRRR(6位对象号+9位块号+3位行号)。此时block#字段从22bit扩展到32bit,以支持单个文件超4M块的容量。你执行SELECT ROWID FROM bigfile_table看到的仍是18字符,但前3位不再是rfile#编码,而是block#高位的一部分。如果误用DBMS_ROWID.ROWID_RELATIVE_FNO解析大文件表空间的ROWID,会返回0——这不是错误,是设计如此。
move table或truncate partition后data_object_id变更,ROWID全失效
data_object_id不是静态的object_id,它随段物理重建而重分配。执行ALTER TABLE ... MOVE、TRUNCATE PARTITION或SHRINK SPACE后,原ROWID全部作废——因为底层数据块被重新组织,data_object_id变了,rfile#和block#也大概率不同。应用层若缓存了ROWID做快速访问(比如分页游标),这类操作后必须刷新缓存,否则SELECT ... WHERE ROWID = 'xxx'会返回空或ORA-01410。
rfile#和FILE_ID之间没有固定换算公式,必须依赖DBA_DATA_FILES.RELATIVE_FNO视图查映射;且DBMS_ROWID包中所有解析函数都默认按小文件表空间逻辑处理,对大文件表空间需额外判断返回值语义。


















