必须满足三个硬性前提:服务端网络连通、tnsnames.ora配置在数据库服务器上(非客户端)、创建者具备CREATE DATABASE LINK或CREATE PUBLIC DATABASE LINK权限;tnsnames.ora仅被数据库实例所在服务器的$ORACLE_HOME/network/admin/目录下文件识别,不读取本地客户端配置。
能直接用 create database link 配置跨服务器访问,但必须满足三个硬性前提:服务端网络连通、tnsnames.ora 配置在数据库服务器上(不是客户端)、创建者有 create database link 或 create public database link 权限。
tnsnames.ora 必须配在数据库服务器上,不是你本地 PL/SQL 客户端
很多人执行 CREATE DATABASE LINK 后一查就报 ORA-12154: TNS:could not resolve service name,根本原因就是把 tnsnames.ora 放错了位置。Oracle 的 DB Link 解析连接串时,只读取数据库实例所在服务器上的 $ORACLE_HOME/network/admin/tnsnames.ora,不认你本机 PL/SQL 或 SQL Developer 里配的别名。
- 先登录到目标数据库服务器(比如用 ssh),确认
tnsnames.ora文件里已定义好远程库的服务名,例如:STUDYTEST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.5.100)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = orcl)) ) - 再在该服务器上用
tnsping STUDYTEST测试是否能通——不通就别往下走了 - 如果不想改
tnsnames.ora,也可以把完整连接描述直接写进USING子句里(见下一条)
USING 子句支持两种写法:tns 名称 or 完整连接字符串
语法上 USING 后面可以填一个字符串,但含义不同:
- 填
'STUDYTEST':表示去服务器上的tnsnames.ora查这个别名 - 填完整描述:
'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.5.100)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl)))':绕过tnsnames.ora,但注意括号要全、引号要闭合、不能换行 - 用完整字符串时,
HOST必须是数据库服务器能直接解析的 IP 或主机名(比如不能写localhost,除非远程库也装在同一台机器上)
PUBLIC 和私有 DB Link 的权限与可见范围差异很大
加不加 PUBLIC 关键字,决定谁能看到、谁可以用:
-
CREATE DATABASE LINK dblink_study ...:私有链接,只有当前用户能用,且不会出现在ALL_DB_LINKS中(得查USER_DB_LINKS) -
CREATE PUBLIC DATABASE LINK dblink_study ...:所有用户都能用,只要他们有访问远程表的权限;它会出现在DBA_DB_LINKS和ALL_DB_LINKS中 - 没有中间态:不能“授权给另一个用户用私有链接”,也不能“把私有改成公共”——只能删了重建
- 如果远程库用户密码含特殊字符(如
@、/),建议用双引号包住密码:IDENTIFIED BY "My@Pass/2026"
测试和排查最常卡在 CONNECT TO 用户没 CREATE SESSION 权限
建完 DB Link 不等于就能查数据。执行 SELECT * FROM emp@dblink_study 报 ORA-01017: invalid username/password 或 ORA-01045: user lacks CREATE SESSION privilege,大概率是远程库那边的账号没开登录权限。
- 登录远程数据库,运行:
GRANT CREATE SESSION TO remote_user; - 如果要用远程库里的同义词或视图,还得确认该用户对那些对象有
SELECT权限 - 查不到数据但也不报错?可能是远程表名大小写问题:
SELECT * FROM "Emp"@dblink和SELECT * FROM emp@dblink可能指向不同对象 - 性能慢?先查
V$DBLINK看连接是否处于OPEN状态,再确认远程库是否有索引、网络延迟是否高
真正容易被忽略的是:DB Link 建立后,每次查询都走一次远程连接认证,它不像连接池那样复用会话。如果高频调用,最好封装成物化视图或定期同步,而不是裸写 @dblink。


















