我是靠谱客的博主 动听小刺猬,这篇文章主要介绍v$和v_$的一些玄机,现在分享给大家,希望可以做个参考。

Oracle的普通用户执行dbms_xplan包查看执行计划,有时会提示错误,

复制代码
1
2
3
SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced')); User has no SELECT privilege on V$SESSION

原因是该用户缺少一些动态性能视图的访问权限,但是当我们尝试将提示的v$session授予用户(例如hr)时,提示了这个错,

复制代码
1
2
3
4
5
6
SQL> grant select on v$session to hr; grant select on v$session to hr * ERROR at line 1: ORA-02030: can only select from fixed tables/views

这就有些玄机了,我是最早从eygle的书中看到的这个问题,一个普通用户,在未授权v$session访问权限的前提下,执行desc v$session,他提示的是v_$session,不是v$session,v_$session和v$session,有什么区别?结合上面的grant错误,应该如何授权?

复制代码
1
2
3
4
SQL> desc v$session; ERROR: ORA-04043: object "SYS"."V_$SESSION" does not exist

首先,我们常用的v$session其实是个同义词,

复制代码
1
2
3
4
5
SQL> select object_name, object_type, owner from dba_objects where object_name='V$SESSION'; OBJECT_NAME OBJECT_TYPE OWNER ------------------------- ----------------------- --------------- V$SESSION SYNONYM PUBLIC

看下他的定义,他是v_$session的同义词,

复制代码
1
2
3
4
5
SQL> select dbms_metadata.get_ddl('SYNONYM','V$SESSION','PUBLIC') from dual; DBMS_METADATA.GET_DDL('SYNONYM','V$SESSION','PUBLIC') -------------------------------------------------------------------------------- CREATE OR REPLACE NONEDITIONABLE PUBLIC SYNONYM "V$SESSION" FOR "SYS"."V_$SESSION"

而v_$session是个视图,

复制代码
1
2
3
4
5
SQL> select object_name, object_type, owner from dba_objects where object_name='V_$SESSION'; OBJECT_NAME OBJECT_TYPE OWNER ------------------------- ----------------------- --------------- V_$SESSION VIEW SYS

这是他的定义,我们看到结尾,v_$session是从v$session视图得到的,

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
SQL> select dbms_metadata.get_ddl('VIEW','V_$SESSION','SYS') from dual; DBMS_METADATA.GET_DDL('VIEW','V_$SESSION','SYS') -------------------------------------------------------------------------------- CREATE OR REPLACE FORCE NONEDITIONABLE VIEW "SYS"."V_$SES SION" CONTAINER_DATA ("SADDR", "SID", "SERIAL#", "AUDSID", "PADDR", "USER#", "USERNAME", "COMMAND", "OWNERID", "TADDR ", "LOCKWAIT", "STATUS", "SERVER", "SCHE MA#", "SCHEMANAME", "OSUSER", "PROCESS", "MACHINE", "PORT", "TERMINAL", "PROGRAM ", "TYPE", "SQL_ADDRESS", "SQL_HASH_VALU E", "SQL_ID", "SQL_CHILD_NUMBER", "SQL_E XEC_START", "SQL_EXEC_ID", "PREV_SQL_ADD R", "PREV_HASH_VALUE", "PREV_SQL_ID", "P REV_CHILD_NUMBER", "PREV_EXEC_START", "P REV_EXEC_ID", "PLSQL_ENTRY_OBJECT_ID", " PLSQL_ENTRY_SUBPROGRAM_ID", "PLSQL_OBJEC T_ID", "PLSQL_SUBPROGRAM_ID", "MODULE", "MODULE_HASH", "ACTION", "ACTION_HASH", "CLIENT_INFO", "FIXED_TABLE_SEQUENCE", " ROW_WAIT_OBJ#", "ROW_WAIT_FILE#", "ROW_W AIT_BLOCK#", "ROW_WAIT_ROW#", "TOP_LEVEL _CALL#", "LOGON_TIME", "LAST_CALL_ET", " PDML_ENABLED", "FAILOVER_TYPE", "FAILOVE R_METHOD", "FAILED_OVER", "RESOURCE_CONS UMER_GROUP", "PDML_STATUS", "PDDL_STATUS ", "PQ_STATUS", "CURRENT_QUEUE_DURATION" , "CLIENT_IDENTIFIER", "BLOCKING_SESSION _STATUS", "BLOCKING_INSTANCE", "BLOCKING _SESSION", "FINAL_BLOCKING_SESSION_STATU S", "FINAL_BLOCKING_INSTANCE", "FINAL_BL OCKING_SESSION", "SEQ#", "EVENT#", "EVEN T", "P1TEXT", "P1", "P1RAW", "P2TEXT", " P2", "P2RAW", "P3TEXT", "P3", "P3RAW", " WAIT_CLASS_ID", "WAIT_CLASS#", "WAIT_CLA SS", "WAIT_TIME", "SECONDS_IN_WAIT", "ST ATE", "WAIT_TIME_MICRO", "TIME_REMAINING _MICRO", "TIME_SINCE_LAST_WAIT_MICRO", " SERVICE_NAME", "SQL_TRACE", "SQL_TRACE_W AITS", "SQL_TRACE_BINDS", "SQL_TRACE_PLA N_STATS", "SESSION_EDITION_ID", "CREATOR _ADDR", "CREATOR_SERIAL#", "ECID", "SQL_ TRANSLATION_PROFILE_ID", "PGA_TUNABLE_ME M", "SHARD_DDL_STATUS", "CON_ID", "EXTER NAL_NAME", "PLSQL_DEBUGGER_CONNECTED") A S select "SADDR","SID","SERIAL#","AUDSID","PADDR","USER#" ,"USERNAME","COMMAND","OWNERID","TADDR", "LOCKWAIT","STATUS","SERVER","SCHEMA#"," SCHEMANAME","OSUSER","PROCESS","MACHINE" ,"PORT","TERMINAL","PROGRAM","TYPE","SQL _ADDRESS","SQL_HASH_VALUE","SQL_ID","SQL _CHILD_NUMBER","SQL_EXEC_START","SQL_EXE C_ID","PREV_SQL_ADDR","PREV_HASH_VALUE", "PREV_SQL_ID","PREV_CHILD_NUMBER","PREV_ EXEC_START","PREV_EXEC_ID","PLSQL_ENTRY_ OBJECT_ID","PLSQL_ENTRY_SUBPROGRAM_ID"," PLSQL_OBJECT_ID","PLSQL_SUBPROGRAM_ID"," MODULE","MODULE_HASH","ACTION","ACTION_H ASH","CLIENT_INFO","FIXED_TABLE_SEQUENCE ","ROW_WAIT_OBJ#","ROW_WAIT_FILE#","ROW_ WAIT_BLOCK#","ROW_WAIT_ROW#","TOP_LEVEL_ CALL#","LOGON_TIME","LAST_CALL_ET","PDML _ENABLED","FAILOVER_TYPE","FAILOVER_METH OD","FAILED_OVER","RESOURCE_CONSUMER_GRO UP","PDML_STATUS","PDDL_STATUS","PQ_STAT US","CURRENT_QUEUE_DURATION","CLIENT_IDE NTIFIER","BLOCKING_SESSION_STATUS","BLOC KING_INSTANCE","BLOCKING_SESSION","FINAL _BLOCKING_SESSION_STATUS","FINAL_BLOCKIN G_INSTANCE","FINAL_BLOCKING_SESSION","SE Q#","EVENT#","EVENT","P1TEXT","P1","P1RA W","P2TEXT","P2","P2RAW","P3TEXT","P3"," P3RAW","WAIT_CLASS_ID","WAIT_CLASS#","WA IT_CLASS","WAIT_TIME","SECONDS_IN_WAIT", "STATE","WAIT_TIME_MICRO","TIME_REMAININ G_MICRO","TIME_SINCE_LAST_WAIT_MICRO","S ERVICE_NAME","SQL_TRACE","SQL_TRACE_WAIT S","SQL_TRACE_BINDS","SQL_TRACE_PLAN_STA TS","SESSION_EDITION_ID","CREATOR_ADDR", "CREATOR_SERIAL#","ECID","SQL_TRANSLATIO N_PROFILE_ID","PGA_TUNABLE_MEM","SHARD_D DL_STATUS","CON_ID","EXTERNAL_NAME","PLS QL_DEBUGGER_CONNECTED" from v$session

一会v$session,一会v_$session,一会又是v$session,有些凌乱了?

用eygle书中说的,概括一下,

"通常大部分用户访问的v$对象,并不是视图,而是指向v_$视图的同义词,而v_$视图是基于真正的v$视图(这个试图是基于x$表创建的)创建的。"

用代码模拟,

(1) 假设x$bisal是从dba_tables复制过来的,

create table x$bisal as select * from dba_tables;

(2) 创建视图v$bisal,他的基表是x$bisal,

create view v$bisal as select * from x$bisal;

(3) 创建视图v_$bisal,他是基于v$bisal视图创建的,

create view v_$bisal as select * from v$bisal;

(4) 创建公共同义词v$bisal,他表示的是v_$bisal视图,

create public synonym v$bisal for v_$bisal;

这说明了什么?说明用户常用的v$bisal并不是真正的视图,他只是个同义词,相当于通过v_$视图将真正底层v$视图和普通用户进行了隔离,v_$视图可以授权给用户,但是真正的v$视图不能直接授权,这就是最开始,授权v$session提示错误的原因,按eygle所说,真正v$视图访问的限制是通过软件机制实现的,不是数据库权限控制的,

复制代码
1
2
3
4
5
6
SQL> grant select on v$session to hr; grant select on v$session to hr * ERROR at line 1: ORA-02030: can only select from fixed tables/views

再者,之所以执行desc提示这个错误,就是因为用户对v$session同义词的检索会解析为对底层视图v_$session的访问,真正v$session视图不允许SYS之外的用户直接访问的,

复制代码
1
2
3
4
SQL> desc v$session; ERROR: ORA-04043: object "SYS"."V_$SESSION" does not exist

了解了这些原因,我们知道如果让用户能访问v$session(同义词),需要授权的是他所代表的v_$session视图,针对执行dbms_xplan的场景,不仅仅是上述提示的v$session,如下这些视图,都需授权,hr用户才可以使用dbms_xplan检索执行计划,

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SQL> grant select on v_$sql_plan to hr; Grant succeeded. SQL> grant select on v_$session to hr;    Grant succeeded. SQL> grant select on v_$sql_plan_statistics_all to hr; Grant succeeded. SQL> grant select on v_$sql to hr; Grant succeeded.

Oracle的这种隔离保护基表的设计,确实值得学习,看似轻描淡写,实则内藏玄机。

近期的热文:

《公众号700篇文章分类和索引》

最后

以上就是动听小刺猬最近收集整理的关于v$和v_$的一些玄机的全部内容,更多相关v$和v_$内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(69)

评论列表共有 0 条评论

立即
投稿
返回
顶部