v$和v_$的一些玄机

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

SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
User has no SELECT privilege on V$SESSION

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

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错误,应该如何授权?

SQL> desc v$session;
ERROR:
ORA-04043: object "SYS"."V_$SESSION" does not exist

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

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的同义词,

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是个视图,

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视图得到的,

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$视图访问的限制是通过软件机制实现的,不是数据库权限控制的,

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之外的用户直接访问的,

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检索执行计划,

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篇文章分类和索引

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值