关于db link权限分配的苦旅(一)

昨天接到一个开发的需求,内容看起来非常简单。
申请数据库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
这个过程的问题明天再来解读。

时间: 2024-09-17 13:18:03

关于db link权限分配的苦旅(一)的相关文章

关于db link权限分配的苦旅(二)

在几天前说过关于db link分配权限的问题,当时也折磨了我好一会儿 http://blog.itpub.net/23718752/viewspace-1869425/ 大体的情况还是在118的服务器中去访问128中的某个表的时候存在一些访问的问题,最后是重建了一个public的db link得以修复,当时对于这个问题的临时处理也是一波三折,还触发了一个oracle的bug,也算是有惊无险. 但是对于之前操作中的疑问在解释之后统一进行解答. 第二天的时候,开发的同事反馈说线上进行测试提dblin

[20130701]db link与事务.txt

[20130701]db link与事务.txt 昨天帮别人修复数据库,安全起见,我先启动read only模式,叫他们检查一些相关数据是否正常,但是在程序界面上出现:ORA-16000: database open for read-only access. 我跟踪发现执行的实际上通过db_link访问远程数据库的语句,不是dml语句(注:实际上执行dml,发生的事务也在远端,不在本地).按照这个道理如果数据库在只读的情况下,是不能访问远端的数据库的. google 发现如下链接: 我回来后在

Shiro系列(2) - 权限模型以及权限分配的两种方式

1. 顶级账户分配权限用户需要被分配相应的权限才可访问相应的资源.权限是对于资源的操作一张许可证.给用户分配资源权限需要将权限的相关信息保存到数据库.这些相关内容包含:用户信息.权限管理.用户分配的权限信息(数据模型) 2. 权限模型设计主体(user.password)权限(权限名称.资源id)/资源(资源名称.访问url)角色(角色名称)角色和权限关系(角色id.权限id)主体和角色关系(主体id.角色id)   3. 权限分配有两种  ​     ​3.1 基于角色的权限控制 这些角色包含

php权限分配的实现

小编今天写下关于后台管理员权限的分配自己的思路想法 <?php /**reader * 小编的思想比较简单实现的功能 * 首先每个栏目的id号是固定不变的 然后 总管理员 * 创建个管理员之后 给该管理员分配权限的时候 把相应的栏目勾选上 * 这样把栏目的 id 号 就插入到数据库里面了,当这个管理员登录之后 * 获得这个管理员 应有的的栏目id 号 .左边的导航 根据当前的栏目id在不在该管理员的 * 栏目id号里 来判断显示或者不显示呢.. */ header("Content-typ

Oracle的DB Link

数据库之间的链接建立在DATABASE LINK上.要创建一个DB LINK,必须先在每个数据库服务器上设置链接字符串. 1. 配置TNS , $ORACLE_HOME/NETWORK/ADMIN/tnsname.ora 10gstandby = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = HFCC-KF-3068)(PORT = 1522)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NA

mysql 新增、删除用户和权限分配_Mysql

1. 新增用户 复制代码 代码如下: mysql>insert into mysql.user(Host,User,Password) values("localhost","lionbule",password("hello1234"));mysql>flush privileges; 2. 修改用户密码 复制代码 代码如下: mysql>update mysql.user set password=password('new

基于php权限分配的实现代码_php实例

小编今天写下关于后台管理员权限的分配自己的思路想法 复制代码 代码如下: <?php /**reader * 小编的思想比较简单实现的功能 * 首先每个栏目的id号是固定不变的 然后 总管理员 * 创建个管理员之后 给该管理员分配权限的时候  把相应的栏目勾选上 * 这样把栏目的 id 号 就插入到数据库里面了,当这个管理员登录之后 * 获得这个管理员 应有的的栏目id 号 .左边的导航 根据当前的栏目id在不在该管理员的  * 栏目id号里 来判断显示或者不显示呢.. */ header(&quo

Oracle global database name与db link的纠缠关系

  ORACLE数据库中Global Database Name与DB LINKS的关系还真是有点纠缠不清,在说清楚这个关系前,我们先来了解一下Global Database Name的概念   Global DataBase Name 概念 1. What is a global database name? ------------------------------------------------------------------------------- The global da

linux 创建用户群与用户组、权限分配的例子

1. 如何在Linux系统下添加一个帐户:用户名为std02,密码为pwd02? :#useradd  std02 #passwd  std02  出现提示输入口令pwd02,再次按提示输入pwd02 也可以: #useradd  -n  std02   -p  pwd02 2. 新建一个子目录/home/public,让它被所有的用户共享,而且拥有所有权限,但不能被非属主删除? :#mkdir  /home/public #chmod  a+trwx  /home/public 3.  让一个