在Oracle数据库里,同义词(synonym)是为表、视图、序列、存储过程等数据库对象建立的别名。它自身不保存任何数据,仅仅在字典中记录一个指向真实对象的指针。当多个schema之间需要互相访问对象,又不想写死schema名时,同义词就非常有用。不过一旦对象被移动、删除或者重建,同义词可能变成无效状态,这时候如果只靠应用报错去排查,效率很低。掌握直接查询数据字典的方法,才能从数据库内部看清这些别名到底指向哪里。

一、Oracle同义词的基本分类
Oracle中的同义词分为私有同义词和公有同义词两种。私有同义词属于某个具体的schema,只有该schema本身以及被授权的用户可以通过这个别名访问目标对象;公有同义词则属于PUBLIC用户组,理论上数据库中所有用户都能直接引用,不需要加schema前缀。理解这种分类,是后续查询时选择不同数据字典视图的前提。
从存储结构上看,同义词信息完全记录在数据字典里,并不占用业务表空间。创建同义词时使用CREATE SYNONYM或CREATE PUBLIC SYNONYM语句,系统会在内部登记表、视图中写入一条映射记录。正因为它是轻量级的指针,所以同义词失效不会影响原表数据,但会让依赖它的SQL语句报出ORA-00980等错误。
二、查询同义词的核心数据字典视图
Oracle提供了三张最常用的视图来查看同义词:USER_SYNONYMS、ALL_SYNONYMS和DBA_SYNONYMS。它们分别对应不同权限范围的可见内容。USER_SYNONYMS只显示当前用户自己拥有的私有同义词;ALL_SYNONYMS显示当前用户能访问的所有同义词,包括私有和有权限的公有同义词;DBA_SYNONYMS则需要DBA权限,能看到数据库中全部同义词。
这三张视图的字段基本一致,主要包含SYNONYM_NAME(同义词名)、TABLE_OWNER(目标对象属主)、TABLE_NAME(目标对象名)、DB_LINK(若指向远程库则记录dblink名)、STATUS(状态,VALID或INVALID)等。通过下面这段SQL,可以列出当前用户下所有同义词及其指向:
SELECT synonym_name, table_owner, table_name, db_link, status FROM user_synonyms ORDER BY synonym_name;
如果你具备DBA权限,想排查整个库中某个表是否被大量同义词引用,可以改用DBA_SYNONYMS并加上过滤条件:
SELECT owner, synonym_name, table_owner, table_name, status FROM dba_synonyms WHERE table_name = 'EMPLOYEES' AND table_owner = 'HR' ORDER BY owner;
三、按不同维度筛选同义词
实际运维中,我们通常不是要看全部同义词,而是按名称、对象类型或状态来定位。比如只查名称里带TMP的临时同义词,可以用LIKE模糊匹配。下面的例子在ALL_SYNONYMS中查找当前用户可访问且名称包含TMP的记录:
SELECT synonym_name, table_owner, table_name, status FROM all_synonyms WHERE synonym_name LIKE '%TMP%' ORDER BY synonym_name;
同义词本身不区分目标对象类型,但我们可以结合ALL_OBJECTS视图来判断它指向的到底是什么。比如要找出所有指向视图的同义词,可以先从ALL_SYNONYMS取出table_owner和table_name,再关联ALL_OBJECTS看object_type。示例如下:
SELECT s.synonym_name, s.table_owner, s.table_name, o.object_type, s.status FROM all_synonyms s JOIN all_objects o ON o.owner = s.table_owner AND o.object_name = s.table_name WHERE o.object_type = 'VIEW' ORDER BY s.synonym_name;
另外,失效同义词是排查重点。STATUS字段为INVALID时,说明目标对象可能已被改动。我们可以用以下语句专门捞出无效同义词:
SELECT synonym_name, table_owner, table_name, status FROM user_synonyms WHERE status = 'INVALID';
四、同义词失效与处理
同义词变成INVALID,常见原因包括目标表被DROP后重建、目标对象所在schema被变更、或者指向的远程dblink失效。Oracle在很多情况下会自动在下次访问时重新校验并恢复VALID,但也可能因为权限回收而永久无法使用。运维时建议定期跑一遍无效同义词检查脚本。
如果发现无效同义词且目标对象依然存在,最简单的修复方式是重新编译或者重建。Oracle没有提供专门的ALTER SYNONYM COMPILE语法,通常直接重建即可:
CREATE OR REPLACE SYNONYM my_sync FOR hr.employees;
若是公有同义词,则需加上PUBLIC关键字并由具备权限的用户执行。重建后再次查询USER_SYNONYMS或DBA_SYNONYMS,STATUS就会回到VALID,应用层的别名访问也就恢复正常了。
五、查询远程同义词与注意事项
当同义词通过dblink指向另一个数据库的表时,DB_LINK字段会有值。这类同义词在本地字典中只记录链路名,真实对象位于远端。查询时若想确认链路是否可用,可以查ALL_DB_LINKS视图。示例如下:
SELECT synonym_name, table_owner, table_name, db_link FROM all_synonyms WHERE db_link IS NOT NULL;
需要注意,公有同义词虽然方便,但容易造成命名冲突。如果本地schema有同名对象,Oracle会优先使用本地对象而非公有同义词。因此在排查为什么同义词“不生效”时,也要确认当前schema下是否存在同名表或视图,这也是查询同义词信息之外必须留心的点。