DB_LINK是Oracle数据库中用于跨实例访问的模式对象,通过CREATE DATABASE LINK创建、DROP DATABASE LINK删除,分PRIVATE(仅创建者可用)和PUBLIC(所有授权用户可用)两类,依赖服务器端tnsnames.ora配置及网络连通性,与PL/SQL客户端工具无关。

PL/SQL 本身不管理数据库链接,真正起作用的是 Oracle 的数据库链接(DB_LINK)对象,它由 CREATE DATABASE LINK 语句创建、DROP DATABASE LINK 删除,且只在会话或数据库级生效。
DB_LINK 是什么,和 PL/SQL 连接不是一回事
很多人混淆“用 PL/SQL 工具连上数据库”和“在 PL/SQL 代码里访问远程数据库”。前者是客户端连接(如 PL/SQL Developer 登录 username/password@MYDB),后者是在已连接的数据库中创建一个指向**另一个 Oracle 数据库**的通道,即 DB_LINK。这个通道由数据库自身维护,与本地 PL/SQL 开发工具无关。
常见错误现象:ORA-02019: connection description for remote database not found —— 表示 DB_LINK 指向的服务名在本地 tnsnames.ora 中未定义,或网络不通。
-
DB_LINK必须在目标数据库(即你当前登录的这个库)中创建,不是在 PL/SQL Developer 界面里配的 - 它依赖底层 Oracle Net 配置:远程数据库的服务名必须能在当前数据库服务器上被解析(即该服务器的
$ORACLE_HOME/network/admin/tnsnames.ora或TNS_ADMIN指向的目录下有对应条目) - 创建时若省略
CONNECT TO ... IDENTIFIED BY ...,则使用当前会话用户身份连接远程库;否则按指定凭据连接
怎么创建和使用 PUBLIC / PRIVATE DB_LINK
权限和可见范围决定用哪种类型:
- PRIVATE(默认):
CREATE DATABASE LINK mylink CONNECT TO scott IDENTIFIED BY tiger USING 'REMOTEDB';—— 只有创建者能用,且必须显式写SELECT * FROM emp@mylink; - PUBLIC:
CREATE PUBLIC DATABASE LINK mylink CONNECT TO scott IDENTIFIED BY tiger USING 'REMOTEDB';—— 所有有权限的用户都能用,无需额外授权 - USING 后的
'REMOTEDB'是本地 tnsnames.ora 里定义的服务名,不是远程库的 IP 或 SID 字符串
注意:USING 值不能是完整 TNS 描述符(如 (DESCRIPTION=...)),否则报 ORA-02085;必须是服务名,且该服务名需在数据库服务器端可解析。
DB_LINK 的权限、安全与常见失效点
权限不到位或配置漂移会导致运行时失败,而非编译时报错:
- 创建
DB_LINK需要CREATE DATABASE LINK权限;PUBLIC 类型还需CREATE PUBLIC DATABASE LINK - 远程库用户(如上面的
scott)必须有对应表的SELECT权限,且不能依赖角色——角色在 DB_LINK 上下文中不生效 - 数据库重启后,
DB_LINK不会消失,但若远程库宕机、监听停止、防火墙拦截或tnsnames.ora被误删,第一次查询就会卡住或超时(默认等待 60 秒) - 避免在循环中高频调用
@mylink,每次访问都建立新连接通道,性能差;应尽量用INSERT /*+ APPEND */ INTO ... SELECT ... FROM remote_table@mylink批量拉取
如何验证和清理 DB_LINK
运行时排查比猜更可靠:
- 查当前用户所有私有链接:
SELECT * FROM USER_DB_LINKS; - 查所有 PUBLIC 链接:
SELECT * FROM ALL_DB_LINKS WHERE OWNER = 'PUBLIC'; - 测试是否可达(不查数据,只验连通):
SELECT SYSDATE FROM DUAL@mylink;—— 成功返回时间即通 - 删除链接:
DROP DATABASE LINK mylink;(PRIVATE)或DROP PUBLIC DATABASE LINK mylink;
容易被忽略的一点:DB_LINK 名称区分大小写(如果建的时候加了双引号),而 USING 的服务名始终不区分大小写;但一旦名称带引号,后续所有引用都必须带引号,否则报 ORA-00942。











