在测试环境玩什么东西忘记了,反正是忽然发现有个没用的表空间“UNDOTBS1”删除不掉,以前写过一篇,如何查找某个对象的定义(V$_X$_DBA),
这里重温一下数据字典和动态性能视图:
UNDOTBS1在v$tablespace中可见,但是不能drop,在dba_tablespaces中不可见,说明数据字典和动态性能视图不匹配了(手工删除了基表导致的,忘记是删除了ts$还是file$内容了):
不得不说Oracle 11.2.0.3以后的版本,对于数据库的一致性校验进行了很人性化的改动,以前这种情况是crash的,现在还open着,带病工作,O(∩_∩)O哈哈~
类似的带病工作的情况,还涉及到很多数据字典的不一致情况,比如以前的i_dependency1, i_dependency2等等。
从这个研究,也证实了如下结论:
V$TABLESPACE的信息是来源于GV$TABLESPACE,GV$TABLESPACE来源于基表 X$KCCTS
而DBA_TABLESPACES是来源于 SYS.TS$ TS 和 SYS.X$KCFISTSA。也就是说,V$TABLESPACE的信息来源于控制文件,而DBA_TABLESPACES的信息是来源于其他基表,手工删除基表信息时,其信息不和控制文件信息同步。
下面有具体看看:
[oracle@lunar ~]$ ss SQL*Plus: Release 11.2.0.3.0 Production on Fri Nov 29 10:36:55 2013 Copyright (c) 1982, 2011, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production With the Partitioning and Real Application Testing options SYS@bb>select name from v$tablespace; NAME ------------------------------------------------------------ SYSTEM SYSAUX UNDOTBS1 TEMP USERS DBTK LUNAR UNDOTBS2 8 rows selected. SYS@bb>drop tablespace undotbs1; drop tablespace undotbs1 * ERROR at line 1: ORA-00959: tablespace 'UNDOTBS1' does not exist SYS@bb> SYS@bb>select tablespace_name from dba_tablespaces; TABLESPACE_NAME ------------------------------------------------------------ SYSTEM SYSAUX TEMP USERS DBTK LUNAR UNDOTBS2 7 rows selected. SYS@bb>
看下创建动态性能视图的语句:
[oracle@lunar ~]$ cat /u01/app/oracle/product/11.2.0.3/dbhome_1/rdbms/admin/catalog.sql |grep -v Rem|grep fixed @@cdfixed.sql [oracle@lunar ~]$ [oracle@lunar ~]$ cat /u01/app/oracle/product/11.2.0.3/dbhome_1/rdbms/admin/cdfixed.sql |grep -v Rem|grep fixed create or replace view v_$fixed_table as select * from v$fixed_table; --- v_$fixed_table 实际上是 v$fixed_table 的view create or replace public synonym v$fixed_table for v_$fixed_table; --- v$fixed_table 是 v_$fixed_table 的同义词 grant select on v_$fixed_table to select_catalog_role; create or replace view v_$fixed_view_definition as --- v_$fixed_view_definition 实际上是 v$fixed_view_definitiond view select * from v$fixed_view_definition; create or replace public synonym v$fixed_view_definition --- v$fixed_view_definition 是 v_$fixed_view_definition 的同义词 for v_$fixed_view_definition; grant select on v_$fixed_view_definition to select_catalog_role; create or replace view v_$indexed_fixed_column as --- v_$indexed_fixed_column 实际上是 v$indexed_fixed_column 的view select * from v$indexed_fixed_column; create or replace public synonym v$indexed_fixed_column --- v$indexed_fixed_column 是 v_$indexed_fixed_column 的同义词 for v_$indexed_fixed_column; grant select on v_$indexed_fixed_column to select_catalog_role; -- Add SQL Performance Analyzer (SPA) fixed views remark Create synonyms for the global fixed views -- global fixed view实际上是从Oracle 8引入的,因为这个版本,Oracle对OPS进行了增强, --- 添加GV$视图就是为了方便全局管理,V$跟GV$的区别就在这里“where inst_id = USERENV('Instance')” --- 也就是V$是本实例的视图,而GV$是全局视图 create or replace view gv_$fixed_table as select * from gv$fixed_table; --- gv_$fixed_table 实际上是 gv$fixed_table 的view create or replace public synonym gv$fixed_table for gv_$fixed_table; --- gv$fixed_table 是 gv_$fixed_table 的同义词 grant select on gv_$fixed_table to select_catalog_role; create or replace view gv_$fixed_view_definition as --- gv_$fixed_view_definition 实际上是 gv$fixed_view_definition 的view select * from gv$fixed_view_definition; create or replace public synonym gv$fixed_view_definition for gv_$fixed_view_definition; grant select on gv_$fixed_view_definition to select_catalog_role; create or replace view gv_$indexed_fixed_column as --- gv_$indexed_fixed_column 实际上是 gv$indexed_fixed_column 的view select * from gv$indexed_fixed_column; create or replace public synonym gv$indexed_fixed_column for gv_$indexed_fixed_column; grant select on gv_$indexed_fixed_column to select_catalog_role; [oracle@lunar ~]$
通过上面建库脚本也可以清晰的看到,得到授权的普通用户仍然只能访问V$开头的视图,而不能直接访问V_$开头的视图,因为实际上V$视图是V_$视图的公有同义词(PUBLIC SYNONYM)要想访问V_$必须带上SYS.V_$,例如
set heading off echo off long 100000 pages 10000 select * from v$fixed_view_definition where view_name='V$TABLESPACE'; SYS@bb>select * from v$fixed_view_definition where view_name='V$TABLESPACE'; V$TABLESPACE select TS# , NAME, INCLUDED_IN_DATABASE_BACKUP, BIGFILE, FLASHBACK_ON, ENCRYPT_IN_BACKUP from GV$TABLESPACE where inst_id = USERENV('Instance') SYS@bb>select * from v$fixed_view_definition where view_name='GV$TABLESPACE'; GV$TABLESPACE select inst_id,tstsn,tsnam, decode(bitand(tsflg, 1+2), 1, 'NO', 2,'NO','YES'), decode(bitand(tsflg, 4), 4,'YES','NO'), decode(bitand(tsflg, 8), 8,'NO','YES'), decode(bitand(tsflg, 16+32), 16, 'ON', 32, 'OFF', to_char(null)) from x$kccts where tstsn != -1 SYS@bb>
而查看普通的DBA_ ALL_ USER_ 等视图,可以查看数据字典 dba_views(这个视图从8i开始引入的)
例如:
set heading off echo off long 1000000000 pages 10000 select text from dba_views where view_name ='DBA_TABLESPACES'; SYS@bb>select text from dba_views where view_name ='DBA_TABLESPACES'; select ts.name, ts.blocksize, ts.blocksize * ts.dflinit, decode(bitand(ts.flags, 3), 1, to_number(NULL), ts.blocksize * ts.dflincr), ts.dflminext, decode(ts.contents$, 1, to_number(NULL), ts.dflmaxext), decode(bitand(ts.flags, 4096), 4096, ts.affstrength, NULL), decode(bitand(ts.flags, 3), 1, to_number(NULL), ts.dflextpct), ts.blocksize * ts.dflminlen, decode(ts.online$, 1, 'ONLINE', 2, 'OFFLINE', 4, 'READ ONLY', 'UNDEFINED'), decode(ts.contents$, 0, (decode(bitand(ts.flags, 16), 16, 'UNDO', 'PERMANENT')), 1, 'TEMPORARY'), decode(bitand(ts.dflogging, 1), 0, 'NOLOGGING', 1, 'LOGGING'), decode(bitand(ts.dflogging, 2), 0, 'NO', 2, 'YES'), decode(ts.bitmapped, 0, 'DICTIONARY', 'LOCAL'), decode(bitand(ts.flags, 3), 0, 'USER', 1, 'SYSTEM', 2, 'UNIFORM', 'UNDEFINED'), decode(ts.plugged, 0, 'NO', 'YES'), decode(bitand(ts.flags,32), 32,'AUTO', 'MANUAL'), decode(bitand(ts.flags,64), 64,'ENABLED', 'DISABLED'), decode(bitand(ts.flags,16), 16, (decode(bitand(ts.flags, 512), 512, 'GUARANTEE', 'NOGUARANTEE')), 'NOT APPLY'), decode(bitand(ts.flags,256), 256, 'YES', 'NO'), decode(tsattr.storattr, 1, 'STORAGE', 'HOST'), decode(bitand(ts.flags,16384), 16384, 'YES', 'NO'), decode(bitand(ts.flags,64), 0, null, (case when bitand(ts.flags, 65536) = 65536 then 'OLTP' when bitand(ts.flags, (131072+262144)) = 131072 then 'QUERY LOW' when bitand(ts.flags, (131072+262144)) = 262144 then 'QUERY HIGH' when bitand(ts.flags, (131072+262144)) = (131072+262144) then 'ARCHIVE LOW' when bitand(ts.flags, 524288) = 524288 then 'ARCHIVE HIGH' else 'BASIC' end)) from sys.ts$ ts, sys.x$kcfistsa tsattr where ts.online$ != 3 and bitand(flags,2048) != 2048 and ts.ts# = tsattr.tsid SYS@bb>
X$ 是 Oracle 数据库 的核心部分,这些表用于跟踪内部数据库信息,维护数据库的正常运行。 X$ 表是加密的(除了MOS和直接看源代码以外,我不知道还有什么方法可以查看X$视图)
Oracle 通过 X$和一些基表(TS$, OBJ$, SEG$等)建立起其他大量视图,提供用户查询和管理数据库。
在9i以前
另外,还可以通过X$KQFTA来查看X$表的相关信息:
X$KQFTA [K]ernel [Q]uery [F]ixed Tables/views Management [TA]bles Column Type Description -------- ---- -------- ADDR RAW(4) address of this row/entry in the array or SGA INDX NUMBER index number of this row in the fixed table array INST_ID NUMBER 8.x oracle instance number KQFTAOBJ NUMBER object ID number - hardcoded in kernel KQFTAVER NUMBER version number KQFTANAM VARCHAR2(30) table name KQFTATYP NUMBER type of table KQFTVTTB 1 declared using KQFTABL KQFTVTTP 2 declared using KQFTABP KQFTVTVI 3 declared using KQFVIEW KQFTVTCB 4 declared using KQFTABC KQFTVTIC 5 declared using KQFTABIC KQFTVTTS 6 declared using KQFTABS KQFTAFLG NUMBER flag KQFTVFONE 1 the INDX column of the table is one based KQFTARSZ NUMBER array element size KQFTACOC NUMBER column count SYS@bb>select KQFTAOBJ, KQFTANAM, KQFTATYP from X$KQFTA where KQFTANAM='X$KCFISTSA'; KQFTAOBJ KQFTANAM KQFTATYP ---------- ------------------------------------------------------------ ---------- 4294952982 X$KCFISTSA 5 SYS@bb>
类似,就是11.2中新引入的X$表:
[oracle@lunar bin]$ strings oracle|grep KCFISTSA
X$KCFISTSA
[oracle@lunar bin]$
在10g和10g以前是没有的:
[oracle@lunar ~]$ . ora102.env [oracle@lunar ~]$ cd $ORACLE_HOME [oracle@lunar db_1]$ cd bin [oracle@lunar bin]$ strings oracle|grep KCFISTSA [oracle@lunar bin]$
实际上,在10g以前的数据库中,
set heading off echo off long 1000000000 pages 10000
select text from dba_views where view_name =’X$KCFISTSA’;
基表数据字典是根据sql.bsq创建的:
[oracle@lunar ~]$ cat /u01/app/oracle/product/11.2.0.3/dbhome_1/rdbms/admin/sql.bsq |grep -v rem|grep -v Rem dcore.bsq dsqlddl.bsq dmanage.bsq dplsql.bsq dtxnspc.bsq dfmap.bsq denv.bsq drac.bsq dsec.bsq doptim.bsq dobj.bsq djava.bsq dpart.bsq drep.bsq daw.bsq dsummgt.bsq dtools.bsq dexttab.bsq ddm.bsq dlmnr.bsq ddst.bsq [oracle@lunar ~]$
回到我们的正题,通过上面查询可以看到,V$TABLESPACE的信息是来源于GV$TABLESPACE,GV$TABLESPACE来源于基表 X$KCCTS
而DBA_TABLESPACES是来源于 SYS.TS$ TS 和 SYS.X$KCFISTSA。也就是说,V$TABLESPACE的信息来源于控制文件,而DBA_TABLESPACES的信息是来源于其他基表,手工删除基表信息时,其信息不和控制文件信息同步,X$KCCTS定义如下
[K]ernel [C]ache [C]ontrolfile management [T]able[S]pace record Column Type Description -------- ---- ----------- ADDR RAW(4) address of this row/entry in the SGA INDX NUMBER index number of this row in the fixed table array INST_ID NUMBER oracle instance number TSRNO NUMBER rec# TSTSN NUMBER TableSpace Number (same as ts# in data dict.) =================关联TS$.TS# TSNAM VARCHAR2(30) tablespace NAMe =================表空间名称 TSNRB NUMBER 8.0 Number of Rollback Segments in the tablespace TSFLG NUMBER 8.1 (rollback segments) Flags defining tablespace KCCTSFTM 0x0001 Tablespace is temporary - Has only tempfiles TSDFP NUMBER tablespace's 1st DataFile Pointer (DataFile rec#) TSPSS VARCHAR2(16) ts Point-in-time recovery mode Start Scn TSPST VARCHAR2(20) ts Point-in-time recov mode Start Timestamp TSPCS VARCHAR2(16) last ts Point-in-time recovery Completion Scn TSPCT VARCHAR2(20) last ts Point-in-time recov Completion Timestp
Bug 13832069 : QUERY USING DBA_TABLESPACES (X$KCFISTSA) CAN LEAK CURSORS AND GIVE WRONG RESULTS
而X$KCFISTSA是定义在kcfis2.h中的,其结构定义如下:
SYS@bb>desc sys.X$KCFISTSA Name Null? Type ---------------------------------------------------------------------------------- -------- ------------------------------------------------------- ADDR RAW(8) INDX NUMBER INST_ID NUMBER TSID NUMBER STORATTR NUMBER SYS@bb> ADDR RAW Address of buffer used to store row. INDX NUMBER Index number (used to uniquely differentiate rows). INST_ID NUMBER Instance number. TSID NUMBER Based on struct element tsid_kcfistsa. tsid_kcfistsa was found in file kcfis2.h, line 377 and is described as : Tablespace ID STORATTR NUMBER Based on struct element storattr_kcfistsa. storattr_kcfistsa was found in file kcfis2.h, line 378 and is described as : Tablespace storage attributes
具体请参考大师的说明:
http://www.juliandyke.com/Internals/FixedTables/X_KCFISTSA.html
再来看看ts$的定义:
SYS@bb>desc sys.TS$; Name Null? Type ---------------------------------------------------------------------------------- -------- ------------------------------------------------------- TS# NOT NULL NUMBER NAME NOT NULL VARCHAR2(30) OWNER# NOT NULL NUMBER ONLINE$ NOT NULL NUMBER CONTENTS$ NOT NULL NUMBER UNDOFILE# NUMBER UNDOBLOCK# NUMBER BLOCKSIZE NOT NULL NUMBER INC# NOT NULL NUMBER SCNWRP NUMBER SCNBAS NUMBER DFLMINEXT NOT NULL NUMBER DFLMAXEXT NOT NULL NUMBER DFLINIT NOT NULL NUMBER DFLINCR NOT NULL NUMBER DFLMINLEN NOT NULL NUMBER DFLEXTPCT NOT NULL NUMBER DFLOGGING NOT NULL NUMBER AFFSTRENGTH NOT NULL NUMBER BITMAPPED NOT NULL NUMBER PLUGGED NOT NULL NUMBER DIRECTALLOWED NOT NULL NUMBER FLAGS NOT NULL NUMBER PITRSCNWRP NUMBER PITRSCNBAS NUMBER OWNERINSTANCE VARCHAR2(30) BACKUPOWNER VARCHAR2(30) GROUPNAME VARCHAR2(30) SPARE1 NUMBER SPARE2 NUMBER SPARE3 VARCHAR2(1000) SPARE4 DATE SYS@bb>
在TS$中,我昨天手工清理了一条NAME=UNDOTBS1的记录,这就是V$TABLESPACE和DBA_TABLESPACES中表空间名称不一致的原因
SYS@bb>select ts#, name, online$ from ts$; TS# NAME ONLINE$ ---------- ------------------------------------------------------------ ---------- 0 SYSTEM 1 1 SYSAUX 1 3 TEMP 1 4 USERS 1 5 LMTBSB 3 6 DBTK 1 7 YKDBAWRTS1 3 8 LUNAR 1 9 UNDOTBS 3 10 UNDOTBS2 1 10 rows selected. SYS@bb>
可以看到,除了我手工删除的一条记录(UNDOTBS1)以外,所有数据库创建以来的表空间名称等信息都保留在TS$中,这样的设计,我猜是为了能够重用表空间名称,减少基表更新等操作(性能考虑吧? 我也不知道,O(∩_∩)O哈哈~)
比如,这里的UNDOTBS和YKDBAWRTS1等都已经是被删除的表空间。
再看看还有那些依赖于X$KCFISTSA的数据字典:
通过查询dependency$,我们可以发现有3个对象依赖于 X$KCFISTSA基表:
SYS@bb>select * from dependency$ where P_OBJ#=4294952982; D_OBJ# D_TIMESTAMP ORDER# P_OBJ# P_TIMESTAMP D_OWNER# PROPERTY D_ATTRS D_REASON ---------- ------------------- ---------- ---------- ------------------- ---------- ---------- --------------- --------------- 4943 2013-06-23 09:37:34 0 4294952982 1991-01-02 00:00:00 5 0003000030 4945 2013-06-23 09:37:34 0 4294952982 1991-01-02 00:00:00 5 0003000030 12409 2013-06-23 09:45:16 30 4294952982 1991-01-02 00:00:00 5 0003000030 SYS@bb> SYS@bb>desc dependency$ Name Null? Type ---------------------------------------------------------------------------------- -------- ------------------------------------------------------- D_OBJ# NOT NULL NUMBER D_TIMESTAMP NOT NULL DATE ORDER# NOT NULL NUMBER P_OBJ# NOT NULL NUMBER P_TIMESTAMP NOT NULL DATE D_OWNER# NUMBER PROPERTY NOT NULL NUMBER D_ATTRS RAW(2000) D_REASON RAW(2000) SYS@bb> 1知道了这个就很清晰了,处理思路:
1,针对file$的不一致信息,需要手工清除:SYS@bb>select file#,status$,ts# from file$ where ts#=2; FILE# STATUS$ TS# ---------- ---------- ---------- 3 2 2 SYS@bb>2,可以根据11g的新特性Health Manager的检查结果来判断,还有哪些相关对象不一致的,是否需要手工清理:
SYS@bb>select obj#,ts#,file# from tab$ where ts#=2; no rows selected SYS@bb>select obj#,ts#,file# from ind$ where ts#=2; no rows selected SYS@bb>3,当其他信息都一致后,针对X$KCCTS的不一致信息,由于其来源于控制文件,那么重建控制文件解决
SYS@bb>select TSTSN,TSNAM from X$KCCTS where TSNAM='UNDOTBS1'; TSTSN TSNAM ---------- ------------------------------------------------------------ 2 UNDOTBS1 SYS@bb>之前就是这个思路错误了,导致了一堆的其他问题,当然,也知道和跟多其他好玩东西,比如用gdb跳过数据库启动时的数据字典检查项,知道了重建控制文件的风险其实很大(在不了解现场情况和重建控制文件的细节时)……