在Oracle分布式环境中,应用经常需要读取其他数据库中的表。最直接做法是在SQL语句中使用数据库链接后缀,例如hr.employees@remote_db。这种方式虽然简单,但当链接名称变化或需要隐藏物理位置时,所有相关SQL都必须修改。同义词(Synonym)提供了一种轻量级别名机制,可以把远程对象映射为本地名称,让应用像访问本地表一样访问远程表。

一、远程表直接访问的局限
先看一个典型写法。假设已经创建了到远端Oracle实例的数据库链接remote_db,要查询远端HR用户下的employees表,SQL如下:
SELECT employee_id, first_name, last_name, salary FROM hr.employees@remote_db WHERE department_id = 50;
这个写法在少量脚本中没有问题,但一旦涉及多个模块,会有三个明显弊端。第一,数据库链接名被硬编码进每一条SQL,未来链接重建、改名或切换到只读备库时,代码改动范围很大。第二,业务开发人员必须知道远端Schema名称,这会暴露数据库内部结构。第三,无法针对不同环境使用不同链接名,测试、预生产、生产部署时容易出现不一致。
同义词的作用就是在本地数据库中建立一个别名。它不复制数据,也不创建中间表,只在数据字典里记录目标对象的位置。应用通过同义词访问时,Oracle会在解析阶段把同义词展开为目标对象,再通过数据库链接发送SQL。
二、创建同义词前的准备与完整SQL
创建同义词前,需要先确保数据库链接可用,并且当前用户对远程对象有SELECT、INSERT等必要权限。远程用户通常需要在远端数据库被授予对应对象权限。数据库链接的创建语法如下:
CREATE DATABASE LINK remote_db CONNECT TO remote_user IDENTIFIED BY remote_password USING '(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.20)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = orclpdb)) )';
注意这里remote_user是远端数据库中的账号,密码和安全策略需要根据实际环境调整。链接创建后,可用SELECT 1 FROM dual@remote_db;测试连通性。然后创建同义词:
CREATE SYNONYM emp_syn FOR hr.employees@remote_db;
如果是公共同义词,使用CREATE PUBLIC SYNONYM emp_syn FOR hr.employees@remote_db;。创建完成后,应用只需要执行SELECT * FROM emp_syn;,不再写@remote_db。对于只读用户,还需要本地授权:GRANT SELECT ON emp_syn TO app_user;。不过需要注意,通过同义词访问远程表时,最终鉴权仍然使用数据库链接中配置的远端账号,本地授权并不能替代远端授权。
同义词创建后可以立即验证:
SELECT COUNT(*) FROM emp_syn; INSERT INTO emp_syn (employee_id, first_name, last_name, email, hire_date, job_id) VALUES (9999, 'Test', 'User', 'test.user@ipipp.com', SYSDATE, 'IT_PROG'); COMMIT;
这里INSERT会直接作用到远端表。用同义词执行DML与本地表体验一致,但要确保数据库链接账号在远端具有DML权限,且远端表没有只读限制。
三、私有同义词与公共同义词的差异
Oracle中同义词分为私有和公有两种。私有同义词归属于某个Schema,只对该Schema及其被授权对象可见;公共同义词属于PUBLIC,所有用户都可以直接引用,除非存在同名私有对象。选择哪种取决于使用范围。一般来说,应用账号私有的访问映射建议使用私有同义词,而需要全局统一名称的场景才使用公共同义词。
解析顺序是容易忽视的问题。当一个用户执行SELECT * FROM emp_syn;时,Oracle先查找当前Schema下是否存在同名对象,包括表、视图、私有同义词等;如果没有,再查找公共同义词。这意味着如果应用Schema下已经有一张名为EMP_SYN的本地表,那么访问到的是本地表而不是公共同义词。排查同义词失效时,应优先确认对象解析路径。
| 比较项 | 私有同义词 | 公共同义词 |
|---|---|---|
| 所属 | 某个Schema | PUBLIC |
| 可见范围 | 所属Schema及被授权用户 | 所有用户 |
| 创建权限 | CREATE SYNONYM | CREATE PUBLIC SYNONYM |
| 典型用途 | 应用内部简化访问 | 全局统一命名 |
| 解析优先级 | 本地对象优先 | 仅在无本地对象时使用 |
权限方面,普通用户创建私有同义词只需要CREATE SYNONYM系统权限;创建公共同义词则需要CREATE PUBLIC SYNONYM。DBA通常会限制CREATE PUBLIC SYNONYM,避免名称冲突影响所有用户。生产环境建议避免创建过多公共同义词,尤其是与应用表同名的公共同义词。
四、同义词参与远程DML与权限传递
同义词不仅用于查询,INSERT、UPDATE、DELETE、MERGE都可以通过同义词执行。比如更新远程员工薪资:
UPDATE emp_syn SET salary = salary * 1.05 WHERE department_id = 50; COMMIT;
但要区分本地权限与远端权限。本地用户需要拥有同义词上的对象权限,例如GRANT UPDATE ON emp_syn TO hr_app;。远端数据库链接账号则需要拥有远程表上的对象权限。两者缺一不可。很多ORA-01031: insufficient privileges错误并非本地问题,而是数据库链接账号在远端没有被授予相应权限。
如果远端表位于只读数据库、物化视图或仅允许查询的账号下,DML会失败。此时应把同义词仅用于查询,并通过GRANT SELECT ON emp_syn TO ...暴露只读能力。另一个细节是事务:通过同义词发起的DML与本地事务一致,提交后才真正持久化到远端数据库。跨库事务会依赖数据库链接的分布式事务能力,网络中断时可能出现悬挂事务,需要监控。
五、同义词管理、排错与视图配合
可以通过数据字典查看同义词定义:
SELECT synonym_name, table_owner, table_name, db_link FROM user_synonyms WHERE synonym_name = 'EMP_SYN'; SELECT owner, synonym_name, table_owner, table_name, db_link FROM all_synonyms WHERE synonym_name = 'EMP_SYN';
输出中DB_LINK列会显示该同义词是否指向远程对象。如果远程表名或链接名修改,需要重建同义词:
DROP SYNONYM emp_syn; CREATE SYNONYM emp_syn FOR hr.employees@remote_db_new;
常见错误包括ORA-00980: synonym translation is no longer valid,通常表示目标对象不存在或数据库链接失效。先测试链接SELECT 1 FROM dual@remote_db;,再通过ALL_SYNONYMS核对TABLE_OWNER、TABLE_NAME和DB_LINK。如果同义词指向的远端对象是视图,需确保视图底层对象可用。
同义词适合隐藏数据库链接和Schema名称,但如果还需要隐藏列、做行级过滤或聚合,应当创建视图。一个常见组合是:本地视图基于同义词或直接基于远程表,然后在视图上再建同义词。例如:
CREATE VIEW emp_public_v AS SELECT employee_id, first_name, last_name, department_id FROM hr.employees@remote_db WHERE active = 'Y'; CREATE PUBLIC SYNONYM emp_public FOR emp_public_v;
这种组合可以同时获得接口稳定、列裁剪和权限控制的好处。总之,同义词是Oracle分布式访问中极轻量的抽象层,几乎不增加维护成本,却能把远程访问细节收敛到数据库内部,是值得长期使用的实践。