关于db link权限分配的苦旅(一) (r7笔记第42天)

时间:2022-05-04
本文章向大家介绍关于db link权限分配的苦旅(一) (r7笔记第42天),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

昨天接到一个开发的需求,内容看起来非常简单。

申请数据库192.168.1.118:1522:TEST下用户APP_TE_FLOW_128赋予对表testore_log的查询权限。。。

貌似这个语句也就几秒钟就可以搞定,直接赋予对象权限,或者角色都可以,

类似grant select on test.testore_log to APP_TE_FLOW_128;

但是这个看似简单的案例,我想用两篇日志来总结,因为里面有许多的内容量,中间的过程也是异常曲折,而且最开始的推论很可能是错误的,然后还可以上升到业务层面。

所以我会按照真实的分析思路来说这个问题,看完之后大家就会明白了。原谅我分析中的错误先。

我直接使用dba账号登录,然后直接使用alter session set current_schema=APP_TE_FLOW_128;然后触发了下面的sql语句。

sys@TEST> select count(*) from testore_log;

select count(*) from testore_log

*

ERROR at line 1:

ORA-00942: table or view does not exist

ORA-02063: preceding line from GCDB

从这个错误可以看出,是使用了db link,但是访问的时候貌似没有访问到。

整个访问的流程类似下面的形式,在ip为118和128都存在一个test用户,两个test用户的数据不同,118库中的 APP_TE_FLOW_128访问的一部分数据是118中的test用户,另外一部分是128总的test用户,当然是间接通过flow0这个用户以 db link的形式来访问。

在118服务器端做检查

sys@TEST> select * from dba_synonyms where synonym_name=upper('testore_log');
OWNER                          SYNONYM_NAME                    TABLE_OWNER                    TABLE_NAME                     DB_LINK
------------------------------ ------------------------------  ------------------------------ ------------------------------ ---------
APP_TE_FLOW_128                testore_log                 TEST                           testore_log                 GCDB

可以看到这个同义词很明显是使用了db link为gcdb

进一步查看db link的情况,发现存在这一些和gcdb相关的db link,都是位于不同的用户下。

sys@TEST> SELECT * FROM DBA_DB_LINKS WHERE DB_LINK='GCDB';
OWNER               DB_LINK  USERNAME  HOST               CREATED
------------------- -------- --------- ------------------ ------------
PUBLIC              GCDB     TLCS0     TEST_TEST_CENTER    23-MAY-11
TEST                GCDB     TEST0     TEST_TEST_CENTER    09-JUN-10
APP_TEST_QUERY_128  GCDB     QUERY0    TEST_TEST_CENTER    09-JUN-10
APP_TE_FLOW_128     GCDB     FLOW0     TEST_TEST_CENTER    09-JUN-10
APP_TE_SDE_128      GCDB     SDE0      TEST_TEST_CENTER    02-JUL-10

然后来得到db link最终的服务信息,最终得到服务器ip即128的服务器

$ tnsping TEST_TEST_CENTER
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS =  (PROTOCOL = TCP)(HOST = TESTcenter.cyou.com)(PORT = 1525)))  (CONNECT_DATA = (SERVICE_NAME = GCDB)))
$ cat /etc/hosts|grep TESTcenter.cyou.com
192.168.1.128  TESTcenter.cyou.com

好了,简单的检查完成,我们继续测试。

切换到APP_TE_FLOW_128下。

sys@TEST> alter session set current_schema=APP_TE_FLOW_128;

Session altered.

然后查看all_synonyms没有得到任何结果,这是一个疑点。

sys@TEST> select * from all_synonyms where owner='APP_TE_FLOW_128' and synonym_name=upper('testore_log');

no rows selected

尝试得到表结构信息,竟然报错了,说明还是可以访问,只是最终访问不通。

sys@TEST> desc testore_log

ERROR:

ORA-04043: object "TEST"."testore_log" does not exist

ORA-02063: preceding line from GCDB

在128服务器端,切换到flow0这个用户

sys@GCDB> alter session set current_schema=FLOW0;

Session altered.

查看权限都没有问题,都是存在的。

sys@GCDB> SELECT * FROM DBA_TAB_PRIVS WHERE TABLE_NAME=upper('testore_log');
GRANTEE            OWNER   TABLE_NAME    GRANTOR   PRIVILEGE    GRA HIE
------------------ ------- ---------------- --------- ------------ --- ---
FLOW0              TEST    testore_log   TEST      SELECT       NO  NO

这是一个疑问,

然后下面的情况就更奇怪了。

在118服务器端,我尝试通过db link来查看gcdb中的数据表的情况。cat基本类似于user_tables

发现118的服务器中存在一个同义词。

sys@TEST> select table_name,table_type from cat@gcdb;
TABLE_NAME                     TABLE_TYPE
------------------------------ -----------
USER_POINT                     SYNONYM

然后我通过dba_synonyms去查看这个同义词,竟然又没有db link的关联,着实奇怪。

sys@TEST> select * from dba_synonyms where synonym_name='USER_POINT';
OWNER                          SYNONYM_NAME                    TABLE_OWNER                    TABLE_NAME                     DB_LINK
------------------------------ ------------------------------  ------------------------------ ------------------------------  ------------------------------
APP_TE_FLOW_128                USER_POINT                     TEST                           USER_POINT

为了更进一步验证,直接查看gcdb中的表user_point的rowid,也没有任何问题,如果想进一步验证,其实会发现还是在128库中的。

sys@TEST> select rowid from user_point@gcdb where rownum<2;
ROWID
------------------
AAAPNRAAHAABdzUAAw

那么这个问题就很奇怪了,看起来解释不通啊。所以这个关系理不清楚,压根没法去赋权限。

继续检查。

在128服务器端继续查看,发现确实有对应的这个表,而且赋予了基本的查询权限。

SQL>SELECT * FROM DBA_TAB_PRIVS WHERE TABLE_NAME='USER_POINT';
GRANTEE                         OWNER                          TABLE_NAME            GRANTOR                        PRIVILEGE                                 GRA HIE
------------------------------ ------------------------------  -------------------- ------------------------------  ---------------------------------------- --- ---
FLOW0                           TEST                           USER_POINT            TEST                           SELECT                                    NO  NO

那么这个问题怎么解释呢,看起来确实是很费神。如果仔细查看前面的线索,其实就会发现一个public的db link其实在暗中操作。

就是最开始我们给出的检查结果。在118的库中确实存在一个public的db link为gcdb.

gc端sys@TEST> SELECT * FROM DBA_DB_LINKS WHERE DB_LINK='GCDB';
OWNER               DB_LINK  USERNAME  HOST               CREATED
------------------- -------- --------- ------------------ ------------
PUBLIC              GCDB     TLCS0     TEST_TEST_CENTER    23-MAY-11

当然我们就会发现那个用户TLCS0在128的库中也确实存在,一切手续都齐全。

sys@GCDB SELECT * FROM DBA_SYNONYMS WHERE OWNER='TLCS0';
OWNER                          SYNONYM_NAME                   TABLE_OWNER                    TABLE_NAME           DB_LINK
------------------------------ ------------------------------  ------------------------------ --------------------  ------------------------------
TLCS0                          USER_POINT                     TEST                           USER_POINT

所以大体通过这个Public的db link我们基本明白了,为什么会出现这种奇怪的现象。

那么问题来了,为什么APP_TE_FLOW_128中的db link没有起作用呢,一种很大的可能性就是这个db link有问题。

首选从dba_users中查到加密后的密码。

sys@GCDB select username,password from dba_users where username='FLOW0';
USERNAME                       PASSWORD
------------------------------ ------------------------------
FLOW0                          BCF5E83CF6EF0269

因为这个db link创建的时间确实很早了,我也压根没法得最终的密码,所以有一种看似不错的方案,那就是使用values的方式来重新创建一个db link来验证一下。这样也不用重新动原来的密码了。

CREATE DATABASE LINK APP_TE_FLOW_128.GC_NEW_LINK CONNECT TO FLOW0 IDENTIFIED BY VALUES 'BCF5E83CF6EF0269' USING 'TEST_TEST_CENTER'

自认为已经解决问题在望,但是做了一个简单的查询,马上让我有些措手不及。持续了十多秒没有反应,我感觉有些问题,马上终止,然后就收到一个600错误。

sys@TEST> select count(*)from test_20151208@APP_TE_FLOW_128.GC_NEW_LINK;

select count(*)from test_20151208@APP_TE_FLOW_128.GC_NEW_LINK

*

ERROR at line 1:

ORA-00600: internal error code, arguments: [kzdlk_zt2 err], [18446744073709551603], [], [], [], [], [], []

这个问题在mos上查看了一番,发现是一个bug,对于values的方式还是存在一定的问题,也是有惊无险。

ORA-00600: [Kzdlk_zt2 Err] While Selecting Using a Database Link (Doc ID 456320.1)

所以使用values的方式创建db link不通,那么我们只能DIY,重新在128的服务器上创建一个用户,做权限分配,然后链接到118的库中。

假设128中创建的用户为flow

sys@GCDB> grant connect to flow0_new;

Grant succeeded.

然后创建了一个新的db link

sys@TEST> conn cydba/cydba

Connected.

cydba@TEST> create database link flow0_128 connect to flow0_new identified by flow0_new using 'TEST_TEST_CENTER';

Database link created.

但是访问有些问题

select count(*) from test_20151208@flow0_128

就马上调整为了public 的db link

create public database link flow0_128 connect to flow0_new identified by flow0_new using 'TEST_TEST_CENTER';

然后再次验证。这次就没有问题了。

 alter session set current_schema=APP_TE_FLOW_128;
 cydba@TEST> select count(*)from TEST.testore_log@flow0_128 where rownum<2;
  COUNT(*)
----------
         1

这个过程的问题明天再来解读。