N年前写的文档,呵呵,还是贴过来。
前言
我们在日常工作中,常常要对Oracle数据字典进行查询,但是很多时候,我们在进行查询的同事却对数据字典的知识不是很了解,这几天我在复习Oracle基础知识的时候,又浏览一遍数据字典的概念,现在把一些相关知识记录下来,方便大家一起总结学习。
数据字典是Oracle数据库的一个重要的组成部分,Oracle通过使用数据字典记录和管理对象信息和安全信息等,用户和数据库系统管理员可以通过数据字典来获取数据库的相关信息。
数据字典包括以下内容:
l 所有数据库schema对象的定义(表、视图、索引、聚簇、同义词、序列、过程、函数、包、触发器等);
l 数据库的空间分配和使用情况;
l 字段的缺省值;
l 完整性约束信息;
l Oracle用户名称、角色、权限等信息;
l 审计信息;
l 其他数据库信息。
一般来说,数据字典都是只读的,通常不建议对任何数据字典表进行修改操作。
通常我们所说的数据字典由4部分组成:内部RDBMS(X$)表、数据字典表、动态性能(v$)视图和数据字典视图,下面我们对这4部分分别进行下讲解。
X$表是oracle数据库的核心部分,这些表用于跟踪内部数据库数据,维护数据库的正常运行。Oracle通过这些X$建立起其他大量视图,提供给用户查询管理数据库之用,也就是说,我们查询的动态视图、数据字典视图等都是通过这些内部表来实现的。
X$表是oracle数据库的运行基础,在数据库启动时由oracle应用程序动态创建。这部分表对数据库来说至关重要,所以oracle不允许sysdba之外的用户直接访问,显示授权不允许。
我们可以通过设置autotrace功能发现构成这些视图的底层表,如下我们最常见的v$session视图的跟踪信息;
SQL> set autotrace trace explain
SQL> select * from v$session;
执行计划
----------------------------------------------------------
Plan hash value: 3733760267
--------------------------------------------------------------------------------
------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)
| Time |
--------------------------------------------------------------------------------
------------
| 0 | SELECT STATEMENT | | 1 | 1065 | 0 (0)
| 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 1065 | 0 (0)
| 00:00:01 |
|* 2 | FIXED TABLE FULL | X$KSUSE | 1 | 856 | 0 (0)
| 00:00:01 |
|* 3 | FIXED TABLE FIXED INDEX| X$KSLED (ind:2) | 1 | 209 | 0 (0)
| 00:00:01 |
--------------------------------------------------------------------------------
通过跟踪,我们可以知道构成这个视图的低层表为X$KSUSE,另外我所知道比较有用的还有X$KSPPI表,该表存放的是隐含参数的信息,不过X$表oracle不作文档说明,这部分的知识属于oracle公司的技术机密,有兴趣的同事可以多研究下。
数据字典表用以存储表、索引、约束以及其他数据库结构的信息。这些对象通常以“$”结尾(如tab$、obj$、ts$等),这些表都是通过运行sql.bsq脚本来创建的。
sql.bsq文件里面包含了这些数据字典表的定义和注释说明,这个我们接触得不多,在这里就不多做研究,有兴趣的可以打开sql.bsq文件看下就知道了,该文件存放在$ORACLE_HOME/RDBMS/ADMIN目录下。
动态性能视图记录了数据库运行时信息和统计数据,大部分动态性能视图被实时更新及反映数据库的当前状态。
Oracle 通过动态性能视图将oracle数据库的状态展示出来提供给用户和数据库管理员,所以其是我们研究和管理数据库的重要依据。
动态视图有GV$和V$两种视图,其中GV$视图的含义是global V$视图,它是为了满足ops环境需要,每个V$视图都有个GV$视图,GV$视图是在V$视图的基础上,多了个INST_ID列,我们以RAC环境为例说明下大家就明白了。
SQL> select inst_id,instance_name,status,version
2 from gv$instance;
INST_ID INSTANCE_NAME STATUS VERSION
---------- ---------------- ------------ -----------------
1 orcl1 OPEN 10.2.0.1.0
2 orcl2 OPEN 10.2.0.1.0
可以看到GV$视图它包含了2个实例的信息,其中inst_id字段保存的是每个节点的情况,oracle提供了一些特殊的视图用以记录其他视图的创建方式。V$fixed_view_definition就是其中一个,我们来查询下刚才哪个gv$instance视图的创建情况
SQL> select * from v_$fixed_view_definition t
2 Where view_name ='GV$INSTANCE'
3 /
VIEW_NAME VIEW_DEFINITION
------------------------------ -------------------------------------------------
GV$INSTANCE select ks.inst_id,ksuxsins,ksuxssid,ksuxshst,ksux
sver,ksuxstim,decode(ksuxssts,0,'STARTED',1,'MOUNTED',2,'OPEN',3,'OPEN MIGRATE',
'UNKNOWN'),decode(ksuxsshr,0,'NO',1,'YES',2,NULL),ksuxsthr,decode(ksuxsarc,0,'ST
OPPED',1,'STARTED','FAILED'),decode(ksuxslsw,0,NULL,2,'ARCHIVE LOG',3,'CLEAR LOG
',4,'CHECKPOINT', 5,'REDO GENERATION'),decode(ksuxsdba,0,'ALLOWED','RESTRI
CTED'),decode(ksuxsshp,0,'NO','YES'),decode(kvitval,0,'ACTIVE',2147483647,'SUSPE
NDED','INSTANCE RECOVERY'),decode(ksuxsrol,1,'PRIMARY_INSTANCE',2,'SECONDARY_INS
TANCE','UNKNOWN'), decode(qui_state,0,'NORMAL',1,'QUIESCING',2,'QUIESCED','UNKNO
WN'), decode(bitand(ksuxsdst, 1), 0, 'NO', 1, 'YES', 'NO') from x$ksuxsinst ks,
x$kvit kv, x$quiesce qu where kvittag = 'kcbwst'
SQL>
我们可以看到GV$INSTANCE视图是由x$ksuxsinst ,x$kvit , x$quiesce三个内部x$表构建成的,同样的道理,我们来查询V$INSTANCE视图,
SQL> select * from v_$fixed_view_definition t
2 Where view_name ='V$INSTANCE'
3 /
VIEW_NAME VIEW_DEFINITION
------------------------------ -------------------------------------------------
-------------------------------
V$INSTANCE select INSTANCE_NUMBER , INSTANCE_NAME , HOST_NAME , VERSION , STARTUP_TIME , STATUS , PARALLEL , THREAD# , ARCHIVER , LOG_SWITCH_WAIT , LOGINS , SHUTDOWN_PENDING, DATABASE_STATUS, INSTANCE_ROLE, ACTIVE_STATE, BLOCKED from GV$INSTANCE where inst_id = USERENV('Instance')
我们可以清楚的看到,其实V$INSTANCE就是查询GV$INSTANCE视图,然后多了个条件inst_id = USERENV('Instance'),再次证明了前面说的每个V$视图都有个GV$视图。
另外,oracle不允许任何对v$视图的授权,这点有同事会问了那为什么我们可以对v$session授予查询的权限呢?其实,oracle在建立GV$和V$视图后,还创建了GV_$和V_$视图,随后为这些视图创建了公共同义词,这些我们可以通过catalog.sql脚本查看。
以下是从catalog.sql脚本中摘要的一些信息:
create or replace view v_$bgprocess as select * from v$bgprocess;
create or replace public synonym v$bgprocess for v_$bgprocess;
grant select on v_$bgprocess to select_catalog_role;
create or replace view v_$session as select * from v$session;
create or replace public synonym v$session for v_$session;
grant select on v_$session to select_catalog_role;
create or replace view v_$license as select * from v$license;
create or replace public synonym v$license for v_$license;
grant select on v_$license to select_catalog_role;
可以看到,我们授予普通用户select 视图v$session的权限,其实是授予的v_$session的视图的权限,这下大家就明白了,实际上大部分对象访问的v$对象,并不是视图,而是v_$视图的同义词,而v_$视图是基于v$视图创建的。
一些常用的动态性能视图如下:
v$controlfile:控制文件的信息;
v$datafile:数据文件的信息;
v$log: 日志文件的信息;
v$process:处理器的信息;
v$session:会话信息;
v$transaction:事务信息;
v$resource:资源信息;
v$sga:系统全局区的信息
数据字典视图是在X$表和数据字典表之上创建的视图。
按照前缀的不同,数据字典视图可以分为3类:
l User_类视图:包括了用户所拥有的相关对象信息。
l All_类视图:包含了用户有权限访问的所有对象的信息。
l DBA_类视图:包含了数据库所有对象的信息。
其实我们可以以这些视图创建结构就可以看到这些视图的区别,我们以user_tables、all_tables、dba_tables来具体的看下,首先是user_tables,其结构如下:
create or replace view user_tables
(table_name, tablespace_name, cluster_name, iot_name, status, pct_free, pct_used, ini_trans,
decode(bitand(o.flags, 128), 128, 'YES', 'NO')
……
from sys.ts$ ts, sys.seg$ s, sys.obj$ co, sys.tab$ t, sys.obj$ o,
sys.obj$ cx, sys.user$ cu, x$ksppcv ksppcv, x$ksppi ksppi
where o.owner# = userenv('SCHEMAID')
and o.obj# = t.obj#
……
and cx.owner# = cu.user# (+)
and ksppi.indx = ksppcv.indx
and ksppi.ksppinm = '_dml_monitoring_enabled'
注意到了where条件下有这样一个限制:
where o.owner# = userenv('SCHEMAID')
这就限制了当前查询只返回当前用户的SCHEMA对象信息。
而对于all_tables视图,在where子句中,关于用户部分的限制为:
and (o.owner# = userenv('SCHEMAID')
or o.obj# in
(select oa.obj#
from sys.objauth$ oa
where grantee# in ( select kzsrorol
from x$kzsro
)
)
or /* user has system privileges */
exists (select null from v$enabledprivs
where priv_number in (-45 /* LOCK ANY TABLE */,
-47 /* SELECT ANY TABLE */,
-48 /* INSERT ANY TABLE */,
-49 /* UPDATE ANY TABLE */,
-50 /* DELETE ANY TABLE */)
)
)
这个条件扩展了关于用户有权限访问的对象信息,所以我们看出来,实际上user_tables的结果是all_tables结果的一个子集。
最后,我们来看一下dba_tables视图的where条件,其信息如下:
where o.owner# = u.user#
and o.obj# = t.obj#
and bitand(t.property, 1) = 0
and bitand(o.flags, 128) = 0
and t.bobj# = co.obj# (+)
and t.ts# = ts.ts#
and t.file# = s.file# (+)
and t.block# = s.block# (+)
and t.ts# = s.ts# (+)
and t.dataobj# = cx.obj# (+)
and cx.owner# = cu.user# (+)
and ksppi.indx = ksppcv.indx
and ksppi.ksppinm = '_dml_monitoring_enabled'
可以看出,没有对于owner的限制,所以查询出来的结果是数据库中所有表的信息,这就是这3类数据字典视图的区别所在。
最后我们来列出一些常用的数据字典视图:
表和列
DBA_TABLES、ALL_TABLES和USER_TABLES显示了有关数据库表的一般信息。
DBA_TAB_COLUMNS、ALL_TAB_COLUMNS和USER_TAB_COLUMNS显示了每个数据库表的列的信息。
注意:DBA_OBJECTS、ALL_OBJECTS和USER_OBJECTS显示了模式对象的信息,包括表。
视图
DBA_VIEWS、ALL_VIEWS和USER_VIEWS。
注意:DBA_OBJECTS、ALL_OBJECTS和USER_OBJECTS显示了模式对象的信息,包括视图。
同义词
DBA_SYNONYMS、ALL_SYNONYMS和USER_SYNONYMS。
注意:DBA_OBJECTS、ALL_OBJECTS和USER_OBJECTS显示了模式对象的信息,包括同义词。
索引
DBA_INDEXS、ALL_INDEXS、USER_INDEXS、DBA_IND_COLUMNS、ALL_IND_COLUMNS和USER_IND_COLUMNS。
以上就是对oracle数据字典的一些总结,不过有些地方可能还比较模糊,大家如果有兴趣,可以进一步深入的研究学习,掌握这些知识对以后进行数据库维护是很有帮助的。