环境:oracle 12.1,一套两节点RAC,两个cdb,要跨cdb从一个cdb中的pdb创建dblink访问另一个cdb中的pdb。
创建完pdb之后,出现如下问题:
检查了一下两个节点的tnsnames.ora,并没有发现什么语法问题,但就是连接不上。
下一步,发现两个节点只有一个节点有tnsnames.ora文件,想着是否和单个节点没有tnsnames.ora有关,于是将1节点的tnsnames.ora复制到2节点,再测,仍然有问题。
下一步,想到自己创建一个dblink,在网上翻了翻怎么创建dblink的文章,找到了tom的:
You Asked
how can i create database links to access remote databases.
please tell me the procedure of creating database links.
and we said...
You need a tnsnames entry in your tnsnames.ora on the server. If you can:
sqlplus scott/tiger@some_other_database
from the machine the server you want to create the database link ON works -- you've gotten the first step done.
For example, I can:
$ sqlplus scott/tiger@ora8idev
SQL*Plus: Release 8.1.5.0.0 - Production on Thu Jul 20 09:16:25 2000
(c) Copyright 1999 Oracle Corporation. All rights reserved.
Connected to:
Oracle8i Enterprise Edition Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production
scott@DEV8I.WORLD>
Once you have that setup, you log into the database (the local database -- the one you want to create the database link in to connect to the OTHER database) and issue the create database link command (see the sql reference manual for complete syntax). For example I can:
scott@8i> create database link ora8idev
2 connect to scott
3 identified by tiger
4 using 'ora8idev'
5 /
Database link created.
scott@8i> select * from dual@ora8idev;
D
-
X
scott@8i>
I do not have to use the connect to and identified by clauses, if I do not, it will use the login and password of the currently connected user to connect to the remote database.
从tom的回答里,我突然得到一个验证dblink的方法,tom将创建dblink分为两步,首先第一步是在客户端服务器创建tnsnames.ora文件,然后通过本地命名的方式验证是否能够访问远程数据库服务器,如果这一步成功,则接下来可进行创建dblink的操作。也就是说,本地命名方式成功访问远程数据库服务器是创建dblink成功的必要条件。
如此一来,我可以先测试本地命名是否能成功登录数据库。经过测试,两节点均不能用本地命名方式登录数据库。可见问题基本定位在此。
这个时候想起创建dblink的两种方式,一种是通过tnsnames.ora来创建,创建命令中只简单包含服务名,第二种则是在创建命令中直接包含所有tnsnames.ora文件信息,这样一来绕过了tnsnames.ora方式无法正常使用dblink,经测试,成功。
下面来验证dblink的两种方式的不同点。
本地服务器主机名为hhu,数据库db_name为PROD;
远端服务器主机名为monit,数据库db_name为ORCL;
1、首先保证两台服务器网络互ping能通
2、在本地没有tnsnames.ora
在PROD上创建dblink,名为non_tns:
create public database link non_tns
connect to hr identified by hr
using '(DESCRIPTION =
(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.56.111)(PORT=1521))
)
(CONNECT_DATA=
(SERVER=DEDICATED)
(SERVICE_NAME=ORCL)
)
)';
测试能否正常访问:
在ORCL本地查询:
二者查询结果一致,能成功访问到ORCL。说明在此种创建dblink的方式下,不需要在本地配置tnsnames.ora同样可以远程访问数据库。
再来看配置tnsnames.ora创建dblink的情况:
配置完成之后报错:
这个时候使用tnsping命令,可以用来辅助定位故障:
可见tnsnames.ora文件格式有问题:
问题就在于多了一对上图高亮的扩号,删除之后,
正常,测试能否通过本地命名访问远程数据库:
然后创建第二个dblink,名为tns:
create database link tns connect to hr identified by hr using 'tns';
测试能否通过dblink tns访问远程数据库ORCL:
同样可以成功访问。
现在将tnsnames.ora改名,再测试dblink tns:
在没有断开原来sqlplus连接的情况下还能访问(因为连接已经建立,没有断开)
断开sqlplus会话,重新连接,用dblink tns远程访问ORCL:
在等待几分钟后,会出现如下结果:
将tnsnames.ora改回来:
同样需要断开重连:
由此可见,tnsnames.ora在第二种创建dblink的方式中,是dblink正常使用的必要条件,如没有它,则dblink无法正常工作。
两种dblink本质区别的猜想:第一种直接在数据字典中创建了dblink,且dblink所有的信息都存放在数据字典中,这种情况下通过dblink访问远程数据库,只需要进入数据字典查找dblink的相关定义即可,所需的所有信息都能找到;而第二种创建dblink的方式,把dblink的主干信息存放在tnsnames.ora文件中,数据字典中只存放dblink的一个名字,通过dblink远程访问数据库的时候,需要先查找数据库字典中的dblink,进而去tnsnames.ora中查找dblink的具体定义,然后才能远程访问数据库。