最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
怎样在Oracle中为开发者创建只能查看执行计划的用户
时间:2026-07-02 11:15:51 编辑:袖梨 来源:一聚教程网
不能直接授SELECT_CATALOG_ROLE,因其包含DBA_*等高危视图权限,会泄露密码哈希、用户信息等敏感数据;应仅授予V$SQL、V$SQL_PLAN、V$SQL_PLAN_STATISTICS_ALL三个最小必要视图权限,并禁用CREATE PROCEDURE和CREATE SYNONYM权限以防绕过。
直接给用户 select any dictionary 或 select_catalog_role 是最常见也最危险的做法——它会让开发者顺手查到 dba_users、dba_tab_privs 甚至加密密码哈希,远超“看执行计划”所需。
为什么不能直接授 SELECT_CATALOG_ROLE?
这个角色包含对 V$SQL_PLAN、V$SQL_PLAN_STATISTICS_ALL 等视图的 SELECT 权限,但同时也开了 DBA_* 和 ALL_* 大量高危视图的门。更关键的是:它不区分“谁的 SQL”,用户能查到所有会话(包括生产应用)的执行计划,可能暴露敏感 SQL 逻辑或绑定变量值。
常见错误现象:
– 用户执行 SELECT * FROM V$SQL_PLAN WHERE SQL_ID = 'xxx' 成功,但紧接着 SELECT PASSWORD FROM DBA_USERS 也成功
– 开发者用 PL/SQL Developer 连接后,在“对象浏览器”里展开 DBA 节点,看到全部用户、表空间、审计策略
只开 V$ 视图的最小权限组合
Oracle 的 V$ 视图是基于底层 X$ 内存结构的封装,权限控制粒度很粗,但可精确限定到具体视图。真正需要的只有三个:
-
V$SQL_PLAN:核心,查任意 SQL 的执行计划(需配合SQL_ID) -
V$SQL_PLAN_STATISTICS_ALL:带实际运行统计(如 buffer gets、rows processed),调试性能必须 -
V$SQL:用于根据 SQL 文本反查SQL_ID,否则开发者连目标 SQL 都找不到
授权语句必须逐个执行(不能用通配符):
GRANT SELECT ON SYS.V$SQL TO dev_plan_user;<br>GRANT SELECT ON SYS.V$SQL_PLAN TO dev_plan_user;<br>GRANT SELECT ON SYS.V$SQL_PLAN_STATISTICS_ALL TO dev_plan_user;
注意:
– 所有视图都属于 SYS Schema,必须写全 SYS.V$XXX
– 授权时不能省略 SYS. 前缀,否则报错 ORA-00942
– 不要授予 V$SESSION 或 V$PROCESS,否则能关联出谁在跑什么 SQL
如何防止用户绕过限制查其他东西?
即使只授了这三个视图,用户仍可能通过以下方式越权:
- 用
EXECUTE IMMEDIATE动态拼接查询其他V$视图(如V$DATABASE)——必须禁用该用户的CREATE PROCEDURE权限 - 利用同义词指向敏感视图——禁止其创建同义词:
REVOKE CREATE SYNONYM FROM dev_plan_user - 通过
DBMS_XPLAN.DISPLAY_CURSOR查计划但不依赖视图——这个包本身需要SELECT_CATALOG_ROLE或显式授权,只要没授就不可用
验证是否干净:
SELECT * FROM SESSION_PRIVS;<br>-- 输出应仅含 CONNECT、SELECT ANY DICTIONARY(若你误授)、以及上面三个 SELECT ON SYS.V$* 权限<br>-- 不应出现 CREATE PROCEDURE、CREATE SYNONYM、UNLIMITED TABLESPACE 等
开发者实际怎么用?给一个安全的查询模板
用户登录后,典型操作是查某条慢 SQL 的计划。正确流程是:
- 先从
V$SQL找SQL_ID(过滤条件必须加,避免扫全表):SELECT SQL_ID, SQL_TEXT FROM V$SQL WHERE SQL_TEXT LIKE '%WHERE order_id = %' AND ROWNUM <= 5; - 再用
SQL_ID查计划:SELECT * FROM V$SQL_PLAN WHERE SQL_ID = 'abc123...' ORDER BY ID; - 如需真实执行统计:
SELECT * FROM V$SQL_PLAN_STATISTICS_ALL WHERE SQL_ID = 'abc123...' AND LAST_ACTIVE_TIME > SYSDATE - 1/24;
关键细节:
– 所有查询必须显式指定 WHERE 条件,尤其 V$SQL 行数巨大,不加限制会卡死会话
– V$SQL_PLAN_STATISTICS_ALL 默认只保留最近缓存的计划,旧 SQL 可能查不到,这不是权限问题,是 Oracle 内存管理机制
真正容易被忽略的点:V$ 视图返回的是当前实例内存中的快照,不是归档历史;如果 SQL 已被老化出共享池,就查不到任何记录——这和权限无关,但常被误判为“权限没生效”。
相关文章
- 如何免费使用办公OA:办公OA免费使用方法指南 07-02
- 培训宝如何进行考勤打卡-培训宝线上培训签到步骤全流程解析 07-02
- 点淘粉丝团如何加入 07-02
- procreate如何翻转画布 07-02
- 国家数字图书馆官网入口在哪里-国家数字图书馆如何免费阅读网页版 07-02
- 婚姻挽回的终极秘诀 07-02