LeiTao
LeiTao
发布于 2026-10-15 / 17 阅读
0
0

Oracle 跨实例 DB Link 排查笔记:ORA-01017 与 ORA-02063

脱敏说明:文中 IP、主机名、账号口令均已脱敏,IP 第三段以 X 占位;Schema / 实例名保留(属非凭据的内部标识)。

环境:Linux + Oracle 19c,单主机双实例。

一、问题现象

在一套新的 UAT 环境(实例 XXMes,Schema XXX_UAT)上,照已有环境的样子新建了一条指向 ERP 测试库的 DB Link。建链语句执行成功,但一使用就报错:

ORA-01017: invalid username/password; logon denied
ORA-02063: 紧接着 line (起自 XXX_PRO_DBLINK)

二、环境拓扑

实例主要 Schema角色DB Link
XXMesXXX_UAT新环境,链接报错ERP_PRO_DBLINK → 同一目标

两个实例跑在同一台数据库主机(192.168.X.26)上,共用同一个 ORACLE_HOME(/u01/app/oracle/product/19.0.0/dbhome_1)。

三、排查:把变量逐个排除

第 1 步 · 网络层

timeout 5 bash -c 'echo > /dev/tcp/192.168.X.166/1521' && echo TCP_OK

返回 TCP_OK,端口可达。

第 2 步 · 拿「能通的对照实例」验证远端账号

在已有环境的链接上做一次最小查询:

SELECT 'LINK_OK' AS result FROM dual@ERP_PRO_DBLINK;

返回 LINK_OK。说明同一个远端库、同一个远端账号,口令是有效的。

第 3 步 · 收敛差异

网络 ✅、服务名 ✅、远端账号 ✅ —— 唯一变动的只剩「建链时填写的口令」。

关键判据(很实用)

报错含义
ORA-01017远端认证失败 → 用户名 / 口令不对
ORA-12514 / ORA-12541 等(同样经 ORA-02063 抛出)网络 / 监听 / 服务名问题
ORA-02019本端找不到这个 DB Link

CREATE DATABASE LINK 执行时不会去登录远端,所以口令填错也照样「创建成功」,要等到第一次真正使用才暴露。

实际现象就是:链接建了两次,都提示成功;直到第一次 select ... from dual@link 才报 ORA-01017。

结论:别把「建链成功」当成「链接可用」,建完必须跟一句验证查询。

五、想从数据库里读回旧链接口令?19c 做不到

三条路都试过,全部不通:

方法结果
DBA_DB_LINKS只有 OWNER / DB_LINK / USERNAME / HOST,没有口令字段
DBMS_METADATA.GET_DDL('DB_LINK', ...)返回掩码:CONNECT TO "..." IDENTIFIED BY VALUES ':1'
以 sysdba 查 SYS.LINK$PASSWORD 列为空;口令加密存于 PASSWORDX(RAW(128)),形如 0730EA5B…(略)

19c 把 DB Link 口令设计成不可逆:即使 SYSDBA 也只能拿到密文,IDENTIFIED BY VALUES ':1' 也不是可用口令。

结论:DB Link 口令一旦丢失就无法从库内取回,只能重新设置;需要口径得找 ERP / DBA 侧要。

登 sysdba 的方式(root 不在 dba 组时需 su - oracle):

su - oracle -c 'export ORACLE_SID=<实例名>; sqlplus -S / as sysdba <<"EOF"
SELECT name, userid, password, passwordx FROM sys."LINK$";
EOF'

六、修复:不用删重建

-- 以链接所属 Schema 执行
ALTER DATABASE LINK "ERP_PRO_DBLINK" CONNECT TO "MES" IDENTIFIED BY "<正确口令>";

-- 回验
SELECT 'LINK_OK' AS result FROM dual@ERP_PRO_DBLINK;
SELECT <列> FROM <其他Schema>.<表>@ERP_PRO_DBLINK WHERE ROWNUM <= 5;

如果确实要删:

DROP DATABASE LINK "ERP_PRO_DBLINK";   -- 注意不是 DROP PUBLIC DATABASE LINK

七、建链参考(脱敏模板)

CREATE DATABASE LINK "ERP_PRO_DBLINK"
  CONNECT TO "MES" IDENTIFIED BY "<口令>"
  USING '(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL = TCP)(HOST = 192.168.X.166)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = toptst)))';

两个注意点:

  1. 建在业务 Schema 下(例如 DMOM_UAT)。因为代码里写的是 表名@ERP_PRO_DBLINK,不限定所有者,靠「当前会话 Schema + PUBLIC」解析;只有要给所有用户用时才建 CREATE PUBLIC DATABASE LINK。
  2. HOST 里直接写完整 TNS 描述,不依赖 tnsnames.ora,跨环境迁移更省事。

八、避坑清单

  • 报错先分层:网络 → 监听 / 服务名 → 远端账号 → 口令 → 本端链接名,别一上来就查 SQL。
  • 同主机多实例时,**优先找「能通的对照实例」**做最小验证,一步就能排除网络和服务名。
  • CREATE DATABASE LINK 成功 ≠ 可用,建完必须验证。
  • 19c 起 DB Link 口令不可逆,别指望从 SYS.LINK$ 捞回明文,也别把 IDENTIFIED BY VALUES ':1' 当成口令。
  • 注意区分 接口 API 口令(例如配置项 ERP.ApiPwd,值形如 ******)与 DB Link 口令 —— 两者完全无关,配置里能看到的那个口令救不了链接。
  • 出现 ORA-01017 时,第一反应应该是「口令」,而不是「权限」或「网络」。

九、常用查询备查

-- 全库 DB Link 清单
SELECT owner, db_link, username, host, created
FROM dba_db_links
ORDER BY owner, db_link;

-- 实际生效的 DB Link 定义(19c 口令在 PASSWORDX,需 sysdba)
SELECT name, userid, passwordx, host FROM sys."LINK$";

-- 本会话可见的链接
SELECT * FROM user_db_links;   -- 仅自己拥有的
SELECT * FROM all_db_links;    -- 自己有权限的 + PUBLIC

评论