OB Oracle系统视图权限导致的故障解决案例
作者:爱可生开源社区
背景
最近在客户这边遇到一个故障,在 Oracle 和 OB Oracle 租户下调用存储过程时,两者表现并不一致,导致获取到的 SQL 文本拼接不完整,影响到了业务侧的功能测试。
客户的存储过程逻辑并不复杂,就是通过查询系统视图 user_tab_columns
来获取用户的表名,然后再进行 SQL 拼接,完成后续的业务逻辑。
本文将针对这个问题进行相关的测试和验证。
问题复现
Oracle 环境中验证
-- 创建测试用户并赋权 [root@localhost ~]# sqlplus / as sysdba SQL> create user u1 identified by u1; User created. SQL> create user u2 identified by u2; User created. SQL> grant connect,resource to u1; Grant succeeded. SQL> grant create procedure to u1; Grant succeeded. SQL> grant connect,resource to u2; Grant succeeded. SQL> grant create synonym to u2; Grant succeeded. SQL> grant select any table to u2; Grant succeeded. -- 创建测试表并赋权 SQL> conn u1/u1 Connected. SQL> create table t1(id int); Table created. SQL> insert into t1(id) values(1); 1 row created. -- 创建表的同义词 SQL> conn u2/u2 Connected. SQL> create synonym t1 for u1.t1; Synonym created. SQL> set lin 200 SQL> col owner for a5 SQL> col table_owner for a5 SQL> col db_link for a10 SQL> select * from all_synonyms where owner='U2'; OWNER SYNONYM_NAME TABLE TABLE_NAME DB_LINK ----- ------------------------------ ----- ------------------------------ ---------- U2 T1 U1 T1 -- 创建存储过程并赋权 SQL> conn u1/u1 Connected. SQL> create or replace procedure proc_case1 as v_str varchar2(10); begin select table_name into v_str from user_tab_columns where table_name='T1'; dbms_output.put_line(v_str); end; / 2 3 4 5 6 7 Procedure created. SQL> grant execute on proc_case1 to u2; Grant succeeded. -- 创建存储过程同义词 SQL> conn u2/u2 Connected. SQL> create synonym proc_case1 for u1.proc_case1; Synonym created. SQL> select * from all_synonyms where owner='U2'; OWNER SYNONYM_NAME TABLE TABLE_NAME DB_LINK ----- ------------------------------ ----- ------------------------------ ---------- U2 PROC_CASE1 U1 PROC_CASE1 U2 T1 U1 T1 -- 验证 SQL> conn u1/u1 Connected. SQL> select * from t1; ID ---------- 1 SQL> set serveroutput on; SQL> call proc_case1(); T1 Call completed. SQL> conn u2/u2 Connected. SQL> select * from t1; ID ---------- 1 SQL> set serveroutput on; SQL> call proc_case1(); T1 Call completed. SQL>
由此可见,在 Oracle 中,无论是 u1 还是 u2 用户,调用存储过程时都能正确返回表名,说明两者查询 user_tab_columns
视图的返回结果是一致的,这也是符合预期的。
OB Oracle 环境中验证
-- 创建测试用户并赋权 SYS[SYS]> create user u1 identified by u1; Query OK, 0 rows affected (0.04 sec) SYS[SYS]> create user u2 identified by u2; Query OK, 0 rows affected (0.04 sec) SYS[SYS]> grant connect,resource to u1; Query OK, 0 rows affected (0.04 sec) SYS[SYS]> grant create procedure to u1; Query OK, 0 rows affected (0.03 sec) SYS[SYS]> grant connect,resource to u2; Query OK, 0 rows affected (0.05 sec) SYS[SYS]> grant create synonym to u2; Query OK, 0 rows affected (0.03 sec) SYS[SYS]> grant select any table to u2; Query OK, 0 rows affected (0.03 sec) -- 创建测试表并赋权 SYS[SYS]> conn u1 Connection id: 269006 Current database: U1 SYS[U1]> create table t1(id int); Query OK, 0 rows affected (0.21 sec) SYS[U1]> insert into t1(id) values(1); Query OK, 1 row affected (0.03 sec) SYS[U1]> commit; Query OK, 0 rows affected (0.01 sec) -- 创建表的同义词 SYS[U1]> conn u2 Connection id: 50837 Current database: U2 SYS[U2]> create synonym t1 for u1.t1; Query OK, 0 rows affected (0.05 sec) SYS[U2]> select * from all_synonyms where owner='U2'; +-------+--------------+-------------+------------+---------+ | OWNER | SYNONYM_NAME | TABLE_OWNER | TABLE_NAME | DB_LINK | +-------+--------------+-------------+------------+---------+ | U2 | T1 | U1 | T1 | NULL | +-------+--------------+-------------+------------+---------+ 2 rows in set (0.01 sec) -- 创建存储过程并赋权 SYS[U2]> conn u1 Connection id: 269078 Current database: U1 SYS[U1]> create or replace procedure proc_case1 as -> v_str varchar2(10); -> begin -> select table_name into v_str from user_tab_columns where table_name='T1'; -> dbms_output.put_line(v_str); -> end; -> / Query OK, 0 rows affected (0.17 sec) SYS[U1]> grant execute on proc_case1 to u2; Query OK, 0 rows affected (0.06 sec) -- 创建存储过程同义词 SYS[U1]> conn u2 Connection id: 50896 Current database: U2 SYS[U2]> create synonym proc_case1 for u1.proc_case1; Query OK, 0 rows affected (0.05 sec) SYS[U2]> select * from all_synonyms where owner='U2'; +-------+--------------+-------------+------------+---------+ | OWNER | SYNONYM_NAME | TABLE_OWNER | TABLE_NAME | DB_LINK | +-------+--------------+-------------+------------+---------+ | U2 | PROC_CASE1 | U1 | PROC_CASE1 | NULL | | U2 | T1 | U1 | T1 | NULL | +-------+--------------+-------------+------------+---------+ 2 rows in set (0.01 sec) -- 验证 SYS[U2]> conn u1 Connection id: 269134 Current database: U1 SYS[U1]> select * from t1; +------+ | ID | +------+ | 1 | +------+ 1 row in set (0.01sec) SYS[U1]> set serveroutput on; Query OK, 0 rows affected (0.41 sec) SYS[U1]> call proc_case1(); Query OK, 0 rows affected (0.21 sec) SYS[U1]> select table_name,column_name from user_tab_columns; +------------+-------------+ | TABLE_NAME | COLUMN_NAME | +------------+-------------+ | C | NAME | | C | ADDRESS | +------------+-------------+ 2 rows in set (0.08 sec)
此处其实已经可以发现一些端倪,在 OB 中虽然可以通过 conn 进行用户切换,切换后的用户也能访问自己的对象,但是在访问 USER_ 等视图时,返回结果与 Oracle 不同。
用户 u1 查询 user_tab_columns
表时,只能看到 SYS 用户下的表( C 表是由 SYS 用户创建的),所以存储过程无法返回 T1 表的表名,其查询结果为空。
-- 直连 u1 用户验证 U1[U1]> select * from t1; +------+ | ID | +------+ | 1 | +------+ 1 row in set (0.01sec) U1[U1]> set serveroutput on; Query OK, 0 rows affected (0.02sec) U1[U1]> call proc_case1(); Query OK, 0 rows affected (0.08sec) T1 U1[U1]> -- 直连 u2 用户进行验证 U2[U2]> select * from t1; +------+ | ID | +------+ | 1 | +------+ 1 row in set (0.03sec) U2[U2]> set serveroutput on; Query OK, 0 rows affected (0.44 sec) U2[U2]> call proc_case1(); Query OK, 0 rows affected (0.43 sec) U2[U2]> select * from user_tab_columns; Empty set (0.08 sec) # 同样地,u2 也无法从 user_tab_columns 视图中查询到 u1 创建的表,调用存储过程返回结果为空 -- 将 user_tab_columns 替换成 all_tab_columns 视图 U2[U2]> select table_name,column_name from all_tab_columns where owner='U1'; +------------+-------------+ | TABLE_NAME | COLUMN_NAME | +------------+-------------+ | T1 | ID | +------------+-------------+ 1 row in set (0.08 sec) U2[U2]> create or replace procedure proc_case2 as -> v_str varchar2(10); -> begin -> select table_name into v_str from all_tab_columns where table_name='T1' and owner='U1'; -> dbms_output.put_line(v_str); -> end; -> / Query OK, 0 rows affected (0.17ec) U2[U2]> call proc_case2(); Query OK, 0 rows affected (0.16ec) T1 U2[U2]> -- 将 SELECT ANY TABLE 权限回收 SYS[SYS]> revoke select any table from u2; Query OK, 0 rows affected (0.03 sec) U2[U2]> select table_name,column_name from all_tab_columns where owner='U1'; Empty set (0.05 sec) U2[U2]> set serveroutput on; Query OK, 0 rows affected (0.01 sec) U2[U2]> call proc_case2(); Query OK, 0 rows affected (0.05 sec)
当用户 u2 没有 SELECT ANY TABLE 系统权限后,即使查询 all_tab_columns
视图,也无法获取其他用户创建表的相关信息。
排查调用系统视图的相关对象
PL 对象
PL 对象,如:函数,存储过程等。
-- dba_source 视图中存放了各种 PL 对象的定义 SQL> select count(*),type from dba_source group by type; COUNT(*) TYPE ---------- ------------ 152202 PROCEDURE 89318 PACKAGE 31504 PACKAGE BODY 1276 TYPE BODY 2210 TRIGGER 3895 FUNCTION 7 JAVA SOURCE 12338 TYPE 8 rows selected. -- 创建测试存储过程(大小写各1个) SQL> CREATE OR REPLACE PROCEDURE PROC_1 IS V_N NUMBER :=0; BEGIN SELECT COUNT(*) INTO V_N FROM USER_TAB_COLUMNS; END; / 2 3 4 5 6 Procedure created. SQL> create or replace procedure proc_2 is v_n number :=0; begin select count(*) into v_n from user_tab_columns; end; / 2 3 4 5 6 Procedure created. -- 查询常用系统视图名(此处只列举了几个与表相关的视图) select owner,object_name,object_type from dba_objects where owner='SYS' and (object_name like 'USER_PART_%' or object_name like 'USER_T%' or object_name like 'ALL_PART_%' or object_name like 'ALL_T%' or object_name like 'DBA_PART_%' or object_name like 'DBA_T%'); -- 根据上一步获取到的系统视图名,通过模糊搜索,即可捕获到涉及查询这些系统视图的 PL 对象 SQL> set line 200 pages 9999 long 999999 SQL> col owner for a10 SQL> col name for a30 SQL> col text for a80 SQL> select owner,name,type,text from dba_source where owner not in('SYS', 'SYSTEM', 'SYSMAN', 'OUTLN', 'DIP', 'TSMSYS', 'DBSNMP', 'ORACLE_OCM', 'WMSYS', 'EXFSYS', 'XDB', 'ANONYMOUS', 'ORDSYS', 'ORDPLUGINS', 'SI_INFORMTN_SCHEMA', 'MDSYS', 'MGMT_VIEW', 'PERFSTAT', 'DMSYS', 'CTXSYS', 'OLAPSYS', 'MDDATA', 'APPQOSSYS', 'XS$NULL', 'ORDDATA', 'SPATIAL_WFS_ADMIN_USR', 'SPATIAL_CSW_ADMIN_USR', 'OWBSYS', 'APEX_PUBLIC_USER', 'APEX_030200', 'FLOWS_FILES', 'SCOTT', 'OMS', 'OWBSYS_AUDIT', 'DSG', 'DBMGR', 'PATROL', 'SPA', 'GOLDENGATE', 'DBADM') and owner not like 'MYNET%' and (text like '%USER_TAB_COLUMNS%' or text like '%user_tab_columns%' or text like '%USER%TABLES%' or text like '%user%tables%' or text like '%ALL_TAB_COLUMNS%' or text like '%ALL_tab_columns%' or text like '%ALL%TABLES%' or text like '%ALL%tables%'); 2 3 4 5 6 7 8 OWNER NAME TYPE TEXT ---------- ------------------------------ ------------ -------------------------------------------------------------------------------- U1 PROC_CASE1 PROCEDURE select table_name into v_str from user_tab_columns where table_name='T1'; ZLM PROC_1 PROCEDURE SELECT COUNT(*) INTO V_N FROM USER_TAB_COLUMNS; ZLM PROC_2 PROCEDURE select count(*) into v_n from user_tab_columns;
视图对象
-- 创建测试视图1 SQL> create view view_1 as select * from user_tables; View created. -- 查询 dba_views 获取视图定义 SQL> select owner,view_name,text from dba_views where owner not in('SYS', 'SYSTEM', 'SYSMAN', 'OUTLN', 'DIP', 'TSMSYS', 'DBSNMP', 'ORACLE_OCM', 'WMSYS', 'EXFSYS', 'XDB', 'ANONYMOUS', 'ORDSYS', 'ORDPLUGINS', 'SI_INFORMTN_SCHEMA', 'MDSYS', 'MGMT_VIEW', 'PERFSTAT', 'DMSYS', 'CTXSYS', 'OLAPSYS', 'MDDATA', 'APPQOSSYS', 'XS$NULL', 'ORDDATA', 'SPATIAL_WFS_ADMIN_USR', 'SPATIAL_CSW_ADMIN_USR', 'OWBSYS', 'APEX_PUBLIC_USER', 'APEX_030200', 'FLOWS_FILES', 'SCOTT', 'OMS', 'OWBSYS_AUDIT', 'DSG', 'DBMGR', 'PATROL', 'SPA', 'GOLDENGATE', 'DBADM') and (text like '%USER_TAB_COLUMNS%' or text like '%user_tab_columns%' or text like '%USER%TABLES%' or text like '%user%tables%' or text like '%ALL_TAB_COLUMNS%' or text like '%ALL_tab_columns%' or text like '%ALL%TABLES%' or text like '%ALL%tables%'); 2 3 4 5 6 7 8 'DBADM') and (text like '%USER_TAB_COLUMNS%' or text like '%user_tab_columns%' or text like '%USER%TABLES%' or text like '%user%tables%' or text like '%ALL_TAB_COLUMNS%' or text like '%ALL_tab_columns%' or text like '%ALL%TABLES%' or text like '%ALL%tables%') * ERROR at line 8: ORA-00932: inconsistent datatypes: expected NUMBER got LONG
dba_source
视图中的 text 列是 varchar2 类型的,可以直接使用 like 进行模糊查询。dba_views
视图中的 text 列是 long 类型的,无法直接使用 like 进行模糊查询,会报 ORA-00932 的错误。
workaround:先创建一张表,用 to_lob
函数将 text 字段转换为 clob 类型,然后将 dba_views 拷贝到该表中,再通过以上 SQL 进行查询。
-- 创建中间表并将系统视图 dba_views 内容拷贝到该表 SQL> create table my_views as select owner,view_name,to_lob(text) text from dba_views; Table created. -- 查询中间表捕获目标视图对象 SQL> select owner,view_name,text from my_views where owner not in('SYS', 'SYSTEM', 'SYSMAN', 'OUTLN', 'DIP', 'TSMSYS', 'DBSNMP', 'ORACLE_OCM', 'WMSYS', 'EXFSYS', 'XDB', 'ANONYMOUS', 'ORDSYS', 'ORDPLUGINS', 'SI_INFORMTN_SCHEMA', 'MDSYS', 'MGMT_VIEW', 'PERFSTAT', 'DMSYS', 'CTXSYS', 'OLAPSYS', 'MDDATA', 'APPQOSSYS', 'XS$NULL', 'ORDDATA', 'SPATIAL_WFS_ADMIN_USR', 'SPATIAL_CSW_ADMIN_USR', 'OWBSYS', 'APEX_PUBLIC_USER', 'APEX_030200', 'FLOWS_FILES', 'SCOTT', 'OMS', 'OWBSYS_AUDIT', 'DSG', 'DBMGR', 'PATROL', 'SPA', 'GOLDENGATE', 'DBADM') and (text like '%USER_TAB_COLUMNS%' or text like '%user_tab_columns%' or text like '%USER%TABLES%' or text like '%user%tables%' or text like '%ALL_TAB_COLUMNS%' or text like '%ALL_tab_columns%' or text like '%ALL%TABLES%' or text like '%ALL%tables%'); 2 3 4 5 6 7 8 OWNER VIEW_NAME TEXT---------- ------------------------------ -------------------------------------------------------------------------------- ZLM VIEW_1 select "TABLE_NAME","TABLESPACE_NAME","CLUSTER_NAME","IOT_NAME","STATUS","PCT_FR EE","PCT_USED","INI_TRANS","MAX_TRANS","INITIAL_EXTENT","NEXT_EXTENT","MIN_EXTEN TS","MAX_EXTENTS","PCT_INCREASE","FREELISTS","FREELIST_GROUPS","LOGGING","BACKED _UP","NUM_ROWS","BLOCKS","EMPTY_BLOCKS","AVG_SPACE","CHAIN_CNT","AVG_ROW_LEN","A VG_SPACE_FREELIST_BLOCKS","NUM_FREELIST_BLOCKS","DEGREE","INSTANCES","CACHE","TA BLE_LOCK","SAMPLE_SIZE","LAST_ANALYZED","PARTITIONED","IOT_TYPE","TEMPORARY","SE CONDARY","NESTED","BUFFER_POOL","ROW_MOVEMENT","GLOBAL_STATS","USER_STATS","DURA TION","SKIP_CORRUPT","MONITORING","CLUSTER_OWNER","DEPENDENCIES","COMPRESSION"," DROPPED" from user_tables
该方法可以满足需求,但每次有新的视图被创建时,需要 drop 并重建表,比较繁琐。
workaround:创建物化视图来代替中间表。
-- 创建物化视图 SQL> create materialized view my_mviews refresh force on demand start with sysdate next sysdate + 10 /(24*60) as select owner,view_name,to_lob(text) text from dba_views; 2 3 4 5 6 7 Materialized view created. -- 创建测试视图2 SQL> CREATE VIEW VIEW_2 AS SELECT * FROM USER_TABLES; View created. -- 查看是否捕获到 view_2 视图 SQL> select owner,view_name,text from my_mviews where owner not in('SYS', 'SYSTEM', 'SYSMAN', 'OUTLN', 'DIP', 'TSMSYS', 'DBSNMP', 'ORACLE_OCM', 'WMSYS', 'EXFSYS', 'XDB', 'ANONYMOUS', 'ORDSYS', 'ORDPLUGINS', 'SI_INFORMTN_SCHEMA', 'MDSYS', 'MGMT_VIEW', 'PERFSTAT', 'DMSYS', 'CTXSYS', 'OLAPSYS', 'MDDATA', 'APPQOSSYS', 'XS$NULL', 'ORDDATA', 'SPATIAL_WFS_ADMIN_USR', 'SPATIAL_CSW_ADMIN_USR', 'OWBSYS', 'APEX_PUBLIC_USER', 'APEX_030200', 'FLOWS_FILES', 'SCOTT', 'OMS', 'OWBSYS_AUDIT', 'DSG', 'DBMGR', 'PATROL', 'SPA', 'GOLDENGATE', 'DBADM') and (text like '%USER_TAB_COLUMNS%' or text like '%user_tab_columns%' or text like '%USER%TABLES%' or text like '%user%tables%' or text like '%ALL_TAB_COLUMNS%' or text like '%ALL_tab_columns%' or text like '%ALL%TABLES%' or text like '%ALL%tables%'); 2 3 4 5 6 7 8 OWNER VIEW_NAME TEXT ---------- ------------------------------ -------------------------------------------------------------------------------- ZLM VIEW_1 select "TABLE_NAME","TABLESPACE_NAME","CLUSTER_NAME","IOT_NAME","STATUS","PCT_FR EE","PCT_USED","INI_TRANS","MAX_TRANS","INITIAL_EXTENT","NEXT_EXTENT","MIN_EXTEN TS","MAX_EXTENTS","PCT_INCREASE","FREELISTS","FREELIST_GROUPS","LOGGING","BACKED _UP","NUM_ROWS","BLOCKS","EMPTY_BLOCKS","AVG_SPACE","CHAIN_CNT","AVG_ROW_LEN","A VG_SPACE_FREELIST_BLOCKS","NUM_FREELIST_BLOCKS","DEGREE","INSTANCES","CACHE","TA BLE_LOCK","SAMPLE_SIZE","LAST_ANALYZED","PARTITIONED","IOT_TYPE","TEMPORARY","SE CONDARY","NESTED","BUFFER_POOL","ROW_MOVEMENT","GLOBAL_STATS","USER_STATS","DURA TION","SKIP_CORRUPT","MONITORING","CLUSTER_OWNER","DEPENDENCIES","COMPRESSION"," DROPPED" from user_tables -- 查看物化视图刷新时间 SQL> select owner,mview_name,last_refresh_type,last_refresh_date from user_mviews; OWNER MVIEW_NAME LAST_REF LAST_REFRESH_DATE ---------- ------------------------------ -------- ------------------- ZLM MY_MVIEWS COMPLETE 2023-08-03 16:07:15 -- 手动刷新物化视图 SQL> exec dbms_mview.refresh('my_mviews'); PL/SQL procedure successfully completed. SQL> select owner,mview_name,last_refresh_type,last_refresh_date from user_mviews; OWNER MVIEW_NAME LAST_REF LAST_REFRESH_DATE ---------- ------------------------------ -------- ------------------- ZLM MY_MVIEWS COMPLETE 2023-08-03 16:21:45 -- 再次查询物化视图,此时 view_2 也能被捕获到了,这样就无需重复建表,当有新视图被创建的时候,只需手动刷新物化视图即可 SQL> select owner,view_name,text from my_mviews where owner not in('SYS', 'SYSTEM', 'SYSMAN', 'OUTLN', 'DIP', 'TSMSYS', 'DBSNMP', 'ORACLE_OCM', 'WMSYS', 'EXFSYS', 'XDB', 'ANONYMOUS', 'ORDSYS', 'ORDPLUGINS', 'SI_INFORMTN_SCHEMA', 'MDSYS', 'MGMT_VIEW', 'PERFSTAT', 'DMSYS', 'CTXSYS', 'OLAPSYS', 'MDDATA', 'APPQOSSYS', 'XS$NULL', 'ORDDATA', 'SPATIAL_WFS_ADMIN_USR', 'SPATIAL_CSW_ADMIN_USR', 'OWBSYS', 'APEX_PUBLIC_USER', 'APEX_030200', 'FLOWS_FILES', 'SCOTT', 'OMS', 'OWBSYS_AUDIT', 'DSG', 'DBMGR', 'PATROL', 'SPA', 'GOLDENGATE', 'DBADM') and (text like '%USER_TAB_COLUMNS%' or text like '%user_tab_columns%' or text like '%USER%TABLES%' or text like '%user%tables%' or text like '%ALL_TAB_COLUMNS%' or text like '%ALL_tab_columns%' or text like '%ALL%TABLES%' or text like '%ALL%tables%'); 2 3 4 5 6 7 8 OWNER VIEW_NAME TEXT ---------- ------------------------------ -------------------------------------------------------------------------------- ZLM VIEW_1 select "TABLE_NAME","TABLESPACE_NAME","CLUSTER_NAME","IOT_NAME","STATUS","PCT_FR EE","PCT_USED","INI_TRANS","MAX_TRANS","INITIAL_EXTENT","NEXT_EXTENT","MIN_EXTEN TS","MAX_EXTENTS","PCT_INCREASE","FREELISTS","FREELIST_GROUPS","LOGGING","BACKED _UP","NUM_ROWS","BLOCKS","EMPTY_BLOCKS","AVG_SPACE","CHAIN_CNT","AVG_ROW_LEN","A VG_SPACE_FREELIST_BLOCKS","NUM_FREELIST_BLOCKS","DEGREE","INSTANCES","CACHE","TA BLE_LOCK","SAMPLE_SIZE","LAST_ANALYZED","PARTITIONED","IOT_TYPE","TEMPORARY","SE CONDARY","NESTED","BUFFER_POOL","ROW_MOVEMENT","GLOBAL_STATS","USER_STATS","DURA TION","SKIP_CORRUPT","MONITORING","CLUSTER_OWNER","DEPENDENCIES","COMPRESSION"," DROPPED" from user_tables ZLM VIEW_2 select "TABLE_NAME","TABLESPACE_NAME","CLUSTER_NAME","IOT_NAME","STATUS","PCT_FR EE","PCT_USED","INI_TRANS","MAX_TRANS","INITIAL_EXTENT","NEXT_EXTENT","MIN_EXTEN TS","MAX_EXTENTS","PCT_INCREASE","FREELISTS","FREELIST_GROUPS","LOGGING","BACKED _UP","NUM_ROWS","BLOCKS","EMPTY_BLOCKS","AVG_SPACE","CHAIN_CNT","AVG_ROW_LEN","A VG_SPACE_FREELIST_BLOCKS","NUM_FREELIST_BLOCKS","DEGREE","INSTANCES","CACHE","TA BLE_LOCK","SAMPLE_SIZE","LAST_ANALYZED","PARTITIONED","IOT_TYPE","TEMPORARY","SE CONDARY","NESTED","BUFFER_POOL","ROW_MOVEMENT","GLOBAL_STATS","USER_STATS","DURA TION","SKIP_CORRUPT","MONITORING","CLUSTER_OWNER","DEPENDENCIES","COMPRESSION"," DROPPED" from USER_TABLES
解决方案
将存储过程中的 user_tab_columns
视图替换成 all_tab_columns
,虽然可作为临时方案,不过存在以下缺点:
- 需要修改业务代码,即替换存储过程中查询相关系统视图的部分。
- 使用同义词来访问对象的用户,需要有 SELECT ANY TABLE 的系统权限,否则即便使用
all_
的视图,也查询不到目标对象。 - 赋予执行用户 dba 权限,并修改原有查询 SQL,增加 owner='XXX' 的条件(存在安全隐患,不推荐)。
- OB 能提供一个 hotfix patch 来彻底解决该问题。
问题总结
在 OB 中,普通用户查询 USER_TAB_COLUMNS
系统视图权限的逻辑与 Oracle 并不一致,导致查询结果有差异。
除了 USER_TAB_COLUMNS
视图,还有其他以 USER_
开头的视图,也存在类似的问题,比如:USER_SYNONYMS
、USER_TABLES
等。
对于系统中已有的对象,应尽快排查并确认在哪些对象中用到了这些系统视图,在该问题被彻底修复前,建议先对相关代码进行临时修改,使其能继续完成后续的功能验证。
以上就是OB Oracle系统视图权限导致的故障解决案例的详细内容,更多关于OB Oracle视图权限故障解决的资料请关注脚本之家其它相关文章!