前几天客户遇上这样一个问题,某个用户A将视图的SELECT给予另一个用户B,但是用户B查询这个视图时,仍然报错:ORA-01031: 权限不足。这是怎么一回事呢?下面来模拟一下这个过程:

有三个用户test1,test2,test3, 三个用户都具有DBA色色权限。

用TEST1用户创建一个表T1,并将其查询权限授予TEST2:

SQL> create table t1 as select * from all_objects;

表已创建。

SQL> grant select on t1 to test2;

授权成功。

用TEST2用户创建一个视图,视图的基表是TEST1.T1,并将查询权限授予TEST3:

SQL> create view v_t1 as select * from test1.t1;

视图已建立。

SQL> grant select on v_t1 to test3;

授权成功。

TEST3用户查询视图TEST2.V_T1:

SQL> select * from test2.v_t1 where rownum<1;
select * from test2.v_t1 where rownum<1
                    *
ERROR 位于第 1 行:
ORA-01031: 权限不足

可以看到报了权限不足的错误,就算这里TEST3用户有DBA权限。
这到底是怎么回事呢?
其实视图的权限,有两点需要引起注意:

1. 视图中,类似于定义者权限的存储过程,是屏蔽了角色权限的。比如如果TEST1没有显式地将T1表的SELECT权限给予TEST2,那么TEST2在创建视图V_T1时也会报ORA-01031错误,即使TEST2用户拥有DBA角色权限。

2.如果在用户A的视图中,引用了其他用户B的表,用户A将视图的访问权限给予用户C,那么就变相地将用户B的表的访问权限给予了用户C,因此,用户A必须有将用户B的表的访问权限转授用户C的权限,也就是用户B在授予A权限时,必须使用with grant option。

显然这里正是由于第2点的原因,导致用户TEST3不能访问视图。用户TEST1执行下面的操作,将解决这个问题:

SQL> grant select on t1 to test2 with grant option;

授权成功。

对于视图的UPDATE,DELETE权限,同样是如此。

在测试时,有一个现象,有点意思。就是如果用户TEST2没有显式地把V_T1的SELECT权限授予TEST3,而TEST3在有SELECT ANY TABLE或DBA权限时,则查询这个视图时不会报权限不足的错误。由于有SELECT ANY TABLE权限的存在,所有的用户表都可以被访问。但是显式授予表的权限时,似乎表的权限有更高的优先级,并且没有跟系统权限和角色权限进行结合。或者版本不同,表现得不一样,在我的测试中,是Oracle 9.2.0.8 for Windows。

,
Trackback

6 comments untill now

  1. 不错哈,老熊,你的blog不错,比很多ace强太多了,顶下。

    老熊 Reply:

    @jarod, 实在是太过奖了。

  2. luolongjiu @ 2009-11-28 12:28

    CORE 9.0.1.1.1 Production
    TNS for 32-bit Windows: Version 9.0.1.1.0 – Production
    版本好像不同测试结果 和你的不一样。

    熊哥不错哈,有大家的水平。

    ACE也有很多强的。

  3. 熊哥请教一个问题:
    一个异地oracle数据库数据同步的问题,由于是两个版本,库表结构一样,需要维护两个版本的数据相同,现在利用触发器记录表的变化,定时程序加工以主键为唯一标识对表数据库数据进行同步。表中有以自增的序列为主键的数据,这样的同步可能造成数据覆盖(id重复)?如何解决这个问题,谢谢您

    老熊 Reply:

    @陶仪, 这样的问题,恐怕没有一个简单的解决办法,不过有以下几个方便供你考虑:
    1.考虑修改主键的生成算法,比如用GUID,或者是在不同的库上的主键加上不同的前缀。
    2.两个库用不同的数值段,比如本地表A的主键用1-1000000,异地表A的主键用1000001-2000000。
    3.如果不改变主键的生成,那么考虑数据同步的处理,在同步INSERT操作时,遇到已经有相同主键的,单独记录,由人工处理,但是如果INSERT之后,紧接着对相同记录有UPDATE这种就不好处理了。

  4. 创建了视图后,授权给test3时,报如下错误
    SQL> grant select on v_t1 to test3;
    grant select on v_t1 to test3
    *
    第 1 行出现错误:
    ORA-01720: 不存在 ‘TEST1.T1′ 的授权选项

Add your comment now